From 01212f0b3d3f13d263cf157128f836496b78b113 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 2 Aug 2010 22:46:41 +0200 Subject: PARISC: led.c - fix potential stack overflow in led_proc_write() commit 4b4fd27c0b5ec638a1f06ced9226fd95229dbbf0 upstream. avoid potential stack overflow by correctly checking count parameter Reported-by: Ilja Signed-off-by: Helge Deller Acked-by: Kyle McMartin Cc: James E.J. Bottomley Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/parisc/led.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 188bc8496a26..d02be78a4138 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -176,16 +176,18 @@ static ssize_t led_proc_write(struct file *file, const char *buf, size_t count, loff_t *pos) { void *data = PDE(file->f_path.dentry->d_inode)->data; - char *cur, lbuf[count + 1]; + char *cur, lbuf[32]; int d; if (!capable(CAP_SYS_ADMIN)) return -EACCES; - memset(lbuf, 0, count + 1); + if (count >= sizeof(lbuf)) + count = sizeof(lbuf)-1; if (copy_from_user(lbuf, buf, count)) return -EFAULT; + lbuf[count] = 0; cur = lbuf; -- cgit v1.2.3 From 2812c8f70ec3a6c5abd0305a42366c880a18a85a Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Tue, 6 Jul 2010 14:03:22 +0300 Subject: arm/imx/gpio: add spinlock protection commit 14cb0deb66fcfca8fdbef75da8c84b5405a8c767 upstream. The GPIO registers need protection from concurrent access for operations that are not atomic. Cc: Juergen Beisert Cc: Daniel Mack Reported-by: rpkamiak@rockwellcollins.com Signed-off-by: Baruch Siach Signed-off-by: Sascha Hauer Signed-off-by: Greg Kroah-Hartman --- arch/arm/plat-mxc/gpio.c | 8 ++++++++ arch/arm/plat-mxc/include/mach/gpio.h | 1 + 2 files changed, 9 insertions(+) diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c index 71437c61cfd7..9ebbd31fe033 100644 --- a/arch/arm/plat-mxc/gpio.c +++ b/arch/arm/plat-mxc/gpio.c @@ -214,13 +214,16 @@ static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset, struct mxc_gpio_port *port = container_of(chip, struct mxc_gpio_port, chip); u32 l; + unsigned long flags; + spin_lock_irqsave(&port->lock, flags); l = __raw_readl(port->base + GPIO_GDIR); if (dir) l |= 1 << offset; else l &= ~(1 << offset); __raw_writel(l, port->base + GPIO_GDIR); + spin_unlock_irqrestore(&port->lock, flags); } static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value) @@ -229,9 +232,12 @@ static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value) container_of(chip, struct mxc_gpio_port, chip); void __iomem *reg = port->base + GPIO_DR; u32 l; + unsigned long flags; + spin_lock_irqsave(&port->lock, flags); l = (__raw_readl(reg) & (~(1 << offset))) | (value << offset); __raw_writel(l, reg); + spin_unlock_irqrestore(&port->lock, flags); } static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset) @@ -285,6 +291,8 @@ int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt) port[i].chip.base = i * 32; port[i].chip.ngpio = 32; + spin_lock_init(&port[i].lock); + /* its a serious configuration bug when it fails */ BUG_ON( gpiochip_add(&port[i].chip) < 0 ); diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h index 894d2f87c856..6bd932c3e4e3 100644 --- a/arch/arm/plat-mxc/include/mach/gpio.h +++ b/arch/arm/plat-mxc/include/mach/gpio.h @@ -36,6 +36,7 @@ struct mxc_gpio_port { int virtual_irq_start; struct gpio_chip chip; u32 both_edges; + spinlock_t lock; }; int mxc_gpio_init(struct mxc_gpio_port*, int); -- cgit v1.2.3 From acdc70839d626fa98417b8905bfa1e88087f3097 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 4 Aug 2010 17:59:39 +0200 Subject: block_dev: always serialize exclusive open attempts commit e75aa85892b2ee78c79edac720868cbef16e62eb upstream. bd_prepare_to_claim() incorrectly allowed multiple attempts for exclusive open to progress in parallel if the attempting holders are identical. This triggered BUG_ON() as reported in the following bug. https://bugzilla.kernel.org/show_bug.cgi?id=16393 __bd_abort_claiming() is used to finish claiming blocks and doesn't work if multiple openers are inside a claiming block. Allowing multiple parallel open attempts to continue doesn't gain anything as those are serialized down in the call chain anyway. Fix it by always allowing only single open attempt in a claiming block. This problem can easily be reproduced by adding a delay after bd_prepare_to_claim() and attempting to mount two partitions of a disk. Signed-off-by: Tejun Heo Reported-by: Markus Trippelsdorf Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/block_dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index 99d6af811747..b3171fb0dc9a 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -681,8 +681,8 @@ retry: if (!bd_may_claim(bdev, whole, holder)) return -EBUSY; - /* if someone else is claiming, wait for it to finish */ - if (whole->bd_claiming && whole->bd_claiming != holder) { + /* if claiming is already in progress, wait for it to finish */ + if (whole->bd_claiming) { wait_queue_head_t *wq = bit_waitqueue(&whole->bd_claiming, 0); DEFINE_WAIT(wait); -- cgit v1.2.3 From 5a8477871f0b45664eedfa352c3942093408a169 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Tue, 3 Aug 2010 20:38:08 -0400 Subject: parisc: pass through '\t' to early (iodc) console commit d9b68e5e88248bb24fd4e455588bea1d56108fd6 upstream. The firmware handles '\t' internally, so stop trying to emulate it (which, incidentally, had a bug in it.) Fixes a really weird hang at bootup in rcu_bootup_announce, which, as far as I can tell, is the first printk in the core kernel to use a tab as the first character. Signed-off-by: Kyle McMartin Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/parisc/kernel/firmware.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index 4c247e02d9b1..df971fa0c32f 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c @@ -1123,7 +1123,6 @@ static char __attribute__((aligned(64))) iodc_dbuf[4096]; */ int pdc_iodc_print(const unsigned char *str, unsigned count) { - static int posx; /* for simple TAB-Simulation... */ unsigned int i; unsigned long flags; @@ -1133,19 +1132,12 @@ int pdc_iodc_print(const unsigned char *str, unsigned count) iodc_dbuf[i+0] = '\r'; iodc_dbuf[i+1] = '\n'; i += 2; - posx = 0; goto print; - case '\t': - while (posx & 7) { - iodc_dbuf[i] = ' '; - i++, posx++; - } - break; case '\b': /* BS */ - posx -= 2; + i--; /* overwrite last */ default: iodc_dbuf[i] = str[i]; - i++, posx++; + i++; break; } } -- cgit v1.2.3 From 8566b8f5bc2fe3f7f179621512ad4805e45bccc1 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 8 Mar 2010 18:29:35 +0100 Subject: amd64_edac: Fix DCT base address selector commit 9975a5f22a4fcc8d08035c65439900a983f891ad upstream. The correct check is to verify whether in high range we're below 4GB and not to extract the DctSelBaseAddr again. See "2.8.5 Routing DRAM Requests" in the F10h BKDG. Signed-off-by: Borislav Petkov Acked-by: Doug Thompson Signed-off-by: Greg Kroah-Hartman --- drivers/edac/amd64_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index ac9f7985096d..5d9e03269ea2 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1430,7 +1430,7 @@ static inline u64 f10_get_base_addr_offset(u64 sys_addr, int hi_range_sel, u64 chan_off; if (hi_range_sel) { - if (!(dct_sel_base_addr & 0xFFFFF800) && + if (!(dct_sel_base_addr & 0xFFFF0000) && hole_valid && (sys_addr >= 0x100000000ULL)) chan_off = hole_off << 16; else -- cgit v1.2.3 From 1c628740e807234af95f299975fda2c3e0115547 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 21 May 2010 21:25:03 +0200 Subject: amd64_edac: Correct scrub rate setting commit bc57117856cf1e581135810b37d3b75f9d1749f5 upstream. Exit early when setting scrub rate on unknown/unsupported families. Signed-off-by: Borislav Petkov Acked-by: Doug Thompson Signed-off-by: Greg Kroah-Hartman --- drivers/edac/amd64_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 5d9e03269ea2..c028acbca768 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -178,7 +178,7 @@ static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 *bandwidth) default: amd64_printk(KERN_ERR, "Unsupported family!\n"); - break; + return -EINVAL; } return amd64_search_set_scrub_rate(pvt->misc_f3_ctl, *bandwidth, min_scrubrate); -- cgit v1.2.3 From 69e18d28ab99ba499e2afba725f16a22f7424a4e Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 3 Aug 2010 16:51:28 +0200 Subject: amd64_edac: Fix operator precendence error commit 962b70a1eb22c467b95756a290c694e73da17f41 upstream. The bitwise AND is of higher precedence, make that explicit. Signed-off-by: Borislav Petkov Signed-off-by: Greg Kroah-Hartman --- drivers/edac/amd64_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index c028acbca768..c20a6c925bbe 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1679,7 +1679,7 @@ static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci, * ganged. Otherwise @chan should already contain the channel at * this point. */ - if (dct_ganging_enabled(pvt) && pvt->nbcfg & K8_NBCFG_CHIPKILL) + if (dct_ganging_enabled(pvt) && (pvt->nbcfg & K8_NBCFG_CHIPKILL)) chan = get_channel_from_ecc_syndrome(mci, syndrome); if (chan >= 0) -- cgit v1.2.3 From 9bfcb1f838ee0825bed898ff34aee2010763499a Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 26 May 2010 00:09:42 +0000 Subject: arp_notify: allow drivers to explicitly request a notification event. commit 06c4648d46d1b757d6b9591a86810be79818b60c upstream. Currently such notifications are only generated when the device comes up or the address changes. However one use case for these notifications is to enable faster network recovery after a virtual machine migration (by causing switches to relearn their MAC tables). A migration appears to the network stack as a temporary loss of carrier and therefore does not trigger either of the current conditions. Rather than adding carrier up as a trigger (which can cause issues when interfaces a flapping) simply add an interface which the driver can use to explicitly trigger the notification. Signed-off-by: Ian Campbell Cc: Stephen Hemminger Cc: Jeremy Fitzhardinge Cc: David S. Miller Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/netdevice.h | 2 ++ include/linux/notifier.h | 1 + net/ipv4/devinet.c | 1 + net/sched/sch_generic.c | 18 ++++++++++++++++++ 4 files changed, 22 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index b21e4054c12c..142bf182caa8 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1775,6 +1775,8 @@ extern void netif_carrier_on(struct net_device *dev); extern void netif_carrier_off(struct net_device *dev); +extern void netif_notify_peers(struct net_device *dev); + /** * netif_dormant_on - mark device as dormant. * @dev: network device diff --git a/include/linux/notifier.h b/include/linux/notifier.h index 540703b555cb..22c2abb61974 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h @@ -210,6 +210,7 @@ static inline int notifier_to_errno(int ret) #define NETDEV_POST_INIT 0x0010 #define NETDEV_UNREGISTER_BATCH 0x0011 #define NETDEV_BONDING_DESLAVE 0x0012 +#define NETDEV_NOTIFY_PEERS 0x0012 #define SYS_DOWN 0x0001 /* Notify of system down */ #define SYS_RESTART SYS_DOWN diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 382bc768ed56..da14c49284f4 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1081,6 +1081,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, } ip_mc_up(in_dev); /* fall through */ + case NETDEV_NOTIFY_PEERS: case NETDEV_CHANGEADDR: /* Send gratuitous ARP to notify of link change */ if (IN_DEV_ARP_NOTIFY(in_dev)) { diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index a63029ef3edd..bd1892fe4b21 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -327,6 +327,24 @@ void netif_carrier_off(struct net_device *dev) } EXPORT_SYMBOL(netif_carrier_off); +/** + * netif_notify_peers - notify network peers about existence of @dev + * @dev: network device + * + * Generate traffic such that interested network peers are aware of + * @dev, such as by generating a gratuitous ARP. This may be used when + * a device wants to inform the rest of the network about some sort of + * reconfiguration such as a failover event or virtual machine + * migration. + */ +void netif_notify_peers(struct net_device *dev) +{ + rtnl_lock(); + call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, dev); + rtnl_unlock(); +} +EXPORT_SYMBOL(netif_notify_peers); + /* "NOOP" scheduler: the best scheduler, recommended for all interfaces under all circumstances. It is difficult to invent anything faster or cheaper. -- cgit v1.2.3 From 2d8acc42551e9c1e184a741d39ad29014b5223a4 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 26 May 2010 00:09:43 +0000 Subject: xen: netfront: explicitly generate arp_notify event after migration. commit 592970675c9522bde588b945388c7995c8b51328 upstream. Use newly introduced netif_notify_peers() method to ensure a gratuitous ARP is generated after a migration. Signed-off-by: Ian Campbell Cc: Stephen Hemminger Cc: Jeremy Fitzhardinge Cc: David S. Miller Cc: netdev@vger.kernel.org Cc: xen-devel@lists.xensource.com Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/xen-netfront.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index d504e2b60257..b50fedcef8ac 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1621,6 +1621,7 @@ static void backend_changed(struct xenbus_device *dev, if (xennet_connect(netdev) != 0) break; xenbus_switch_state(dev, XenbusStateConnected); + netif_notify_peers(netdev); break; case XenbusStateClosing: -- cgit v1.2.3 From a436d816e9abf39ecc1cf3df6c99457caf94453d Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Tue, 29 Jun 2010 18:12:05 +0000 Subject: e1000e: don't inadvertently re-set INTX_DISABLE commit 36f2407fe52c55566221f8c68c8fb808abffd2f5 upstream. Should e1000_test_msi() fail to see an msi interrupt, it attempts to fallback to legacy INTx interrupts. But an error in the code may prevent this from happening correctly. Before calling e1000_test_msi_interrupt(), e1000_test_msi() disables SERR by clearing the SERR bit from the just read PCI_COMMAND bits as it writes them back out. Upon return from calling e1000_test_msi_interrupt(), it re-enables SERR by writing out the version of PCI_COMMAND it had previously read. The problem with this is that e1000_test_msi_interrupt() calls pci_disable_msi(), which eventually ends up in pci_intx(). And because pci_intx() was called with enable set to 1, the INTX_DISABLE bit gets cleared from PCI_COMMAND, which is what we want. But when we get back to e1000_test_msi(), the INTX_DISABLE bit gets inadvertently re-set because of the attempt by e1000_test_msi() to re-enable SERR. The solution is to have e1000_test_msi() re-read the PCI_COMMAND bits as part of its attempt to re-enable SERR. During debugging/testing of this issue I found that not all the systems I ran on had the SERR bit set to begin with. And on some of the systems the same could be said for the INTX_DISABLE bit. Needless to say these latter systems didn't have a problem falling back to legacy INTx interrupts with the code as is. Signed-off-by: Dean Nelson Tested-by: Emil Tantilov Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/e1000e/netdev.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 57a7e41da69e..79e38dc60a43 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -3419,13 +3419,18 @@ static int e1000_test_msi(struct e1000_adapter *adapter) /* disable SERR in case the MSI write causes a master abort */ pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd); - pci_write_config_word(adapter->pdev, PCI_COMMAND, - pci_cmd & ~PCI_COMMAND_SERR); + if (pci_cmd & PCI_COMMAND_SERR) + pci_write_config_word(adapter->pdev, PCI_COMMAND, + pci_cmd & ~PCI_COMMAND_SERR); err = e1000_test_msi_interrupt(adapter); - /* restore previous setting of command word */ - pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd); + /* re-enable SERR */ + if (pci_cmd & PCI_COMMAND_SERR) { + pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd); + pci_cmd |= PCI_COMMAND_SERR; + pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd); + } /* success ! */ if (!err) -- cgit v1.2.3 From 0c41742f8b41c3fd81f96bffc8c65bbb1f0a0d8b Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Tue, 27 Jul 2010 12:28:46 +0000 Subject: e1000e: 82577/82578 PHY register access issues commit ff847ac2d3e90edd94674c28bade25ae1e6a2e49 upstream. The MAC-PHY interconnect on 82577/82578 uses a power management feature (called K1) which must be disabled when in 1Gbps due to a hardware issue on these parts. The #define bit setting used to enable/disable K1 is incorrect and can cause PHY register accesses to stop working altogether until the next device reset. This patch sets the register correctly. This issue is present in kernels since 2.6.32. Signed-off-by: Bruce Allan Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/e1000e/hw.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 5d1220d188d4..664ed5812cff 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -308,7 +308,7 @@ enum e1e_registers { #define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */ #define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ #define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 -#define E1000_KMRNCTRLSTA_K1_ENABLE 0x140E +#define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002 #define E1000_KMRNCTRLSTA_K1_DISABLE 0x1400 #define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 -- cgit v1.2.3 From edea2aceac3068aab66f0fe748ffc1c3125587da Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 9 Jul 2010 23:51:54 +0000 Subject: 9p: strlen() doesn't count the terminator commit 5c4bfa17f3ec46becec4b23d12323f7605ebd696 upstream. This is an off by one bug because strlen() doesn't count the NULL terminator. We strcpy() addr into a fixed length array of size UNIX_PATH_MAX later on. The addr variable is the name of the device being mounted. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/9p/trans_fd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 98ce9bcb0e15..c85109d809ca 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -948,7 +948,7 @@ p9_fd_create_unix(struct p9_client *client, const char *addr, char *args) csocket = NULL; - if (strlen(addr) > UNIX_PATH_MAX) { + if (strlen(addr) >= UNIX_PATH_MAX) { P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n", addr); return -ENAMETOOLONG; -- cgit v1.2.3 From 21b2bf38c8c49bd8a2b41676f51be82ab228d711 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Thu, 1 Jul 2010 13:38:16 +0000 Subject: igb: Use only a single Tx queue in SR-IOV mode commit 5fa8517f038d51d571981fb495206cc30ed91b06 upstream. The 82576 expects the second rx queue in any pool to receive L2 switch loop back packets sent from the second tx queue in another pool. The 82576 VF driver does not enable the second rx queue so if the PF driver sends packets destined to a VF from its second tx queue then the VF driver will never see them. In SR-IOV mode limit the number of tx queues used by the PF driver to one. This patch fixes a bug reported in which the PF cannot communciate with the VF and should be considered for 2.6.34 stable. Signed-off-by: Greg Rose Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/igb/igb_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index cea37e0837ff..df2a6d7c23af 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -630,9 +630,6 @@ static void igb_cache_ring_register(struct igb_adapter *adapter) for (; i < adapter->rss_queues; i++) adapter->rx_ring[i]->reg_idx = rbase_offset + Q_IDX_82576(i); - for (; j < adapter->rss_queues; j++) - adapter->tx_ring[j]->reg_idx = rbase_offset + - Q_IDX_82576(j); } case e1000_82575: case e1000_82580: @@ -996,7 +993,10 @@ static void igb_set_interrupt_capability(struct igb_adapter *adapter) /* Number of supported queues. */ adapter->num_rx_queues = adapter->rss_queues; - adapter->num_tx_queues = adapter->rss_queues; + if (adapter->vfs_allocated_count) + adapter->num_tx_queues = 1; + else + adapter->num_tx_queues = adapter->rss_queues; /* start with one vector for every rx queue */ numvecs = adapter->num_rx_queues; -- cgit v1.2.3 From 8e5ad4d847e303d1d523c87566edfc58a67e05c0 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 28 Jul 2010 10:06:35 -0400 Subject: ath9k: enable serialize_regmode for non-PCIE AR9160 commit 4c85ab11ca56da1aa59b58c80cc6a356515cc645 upstream. https://bugzilla.kernel.org/show_bug.cgi?id=16476 Signed-off-by: John W. Linville Acked-by: Luis R. Rodriguez Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/hw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index c33f17dbe6f1..10419658d03a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -537,7 +537,8 @@ static int __ath9k_hw_init(struct ath_hw *ah) if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) { if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI || - (AR_SREV_9280(ah) && !ah->is_pciexpress)) { + ((AR_SREV_9160(ah) || AR_SREV_9280(ah)) && + !ah->is_pciexpress)) { ah->config.serialize_regmode = SER_REG_MODE_ON; } else { -- cgit v1.2.3 From 94230128c1fb1eb2fa607875804bc1d5d111c98c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 7 Jul 2010 19:42:08 +0200 Subject: ath9k: fix a potential buffer leak in the STA teardown path commit 2b40994cabd2f545d5c11d3a65dcee6f6f9155f8 upstream. It looks like it might be possible for a TID to be paused, while still holding some queued buffers, however ath_tx_node_cleanup currently only iterates over active TIDs. Fix this by always checking every allocated TID for the STA that is being cleaned up. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/xmit.c | 52 +++++++++++++++++------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 859aa4ab0769..ac7b88f23d57 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2449,37 +2449,37 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) { - int i; - struct ath_atx_ac *ac, *ac_tmp; - struct ath_atx_tid *tid, *tid_tmp; + struct ath_atx_ac *ac; + struct ath_atx_tid *tid; struct ath_txq *txq; + int i, tidno; - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (ATH_TXQ_SETUP(sc, i)) { - txq = &sc->tx.txq[i]; + for (tidno = 0, tid = &an->tid[tidno]; + tidno < WME_NUM_TID; tidno++, tid++) { + i = tid->ac->qnum; - spin_lock_bh(&txq->axq_lock); + if (!ATH_TXQ_SETUP(sc, i)) + continue; - list_for_each_entry_safe(ac, - ac_tmp, &txq->axq_acq, list) { - tid = list_first_entry(&ac->tid_q, - struct ath_atx_tid, list); - if (tid && tid->an != an) - continue; - list_del(&ac->list); - ac->sched = false; - - list_for_each_entry_safe(tid, - tid_tmp, &ac->tid_q, list) { - list_del(&tid->list); - tid->sched = false; - ath_tid_drain(sc, txq, tid); - tid->state &= ~AGGR_ADDBA_COMPLETE; - tid->state &= ~AGGR_CLEANUP; - } - } + txq = &sc->tx.txq[i]; + ac = tid->ac; - spin_unlock_bh(&txq->axq_lock); + spin_lock_bh(&txq->axq_lock); + + if (tid->sched) { + list_del(&tid->list); + tid->sched = false; + } + + if (ac->sched) { + list_del(&ac->list); + tid->ac->sched = false; } + + ath_tid_drain(sc, txq, tid); + tid->state &= ~AGGR_ADDBA_COMPLETE; + tid->state &= ~AGGR_CLEANUP; + + spin_unlock_bh(&txq->axq_lock); } } -- cgit v1.2.3 From 5776fe6ec7296d5f89b8979d6f6958e1be8fd706 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 11 Jul 2010 12:48:42 +0200 Subject: ath9k_hw: prevent a fast channel change after a rx DMA stuck issue commit 9cc2f3e881dcda5466c55ffe8dd0a9d1433469cb upstream. If the receive path gets stuck, a full hardware reset is necessary to recover from it. If this happens during a scan, the whole scan might fail, as each channel change bypasses the full reset sequence. Fix this by resetting the fast channel change flag if stopping the receive path fails. This will reduce the number of error messages that look like this: ath: DMA failed to stop in 10 ms AR_CR=0x00000024 AR_DIAG_SW=0x40000020 Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/hw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 10419658d03a..079b9638bef5 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1233,9 +1233,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (!ah->chip_fullsleep) { ath9k_hw_abortpcurecv(ah); - if (!ath9k_hw_stopdmarecv(ah)) + if (!ath9k_hw_stopdmarecv(ah)) { ath_print(common, ATH_DBG_XMIT, "Failed to stop receive dma\n"); + bChannelChange = false; + } } if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) -- cgit v1.2.3 From 52166187243a4887bf3ed3aa2cd0452feb307e87 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 11 Jul 2010 12:48:40 +0200 Subject: ath9k_hw: fix a sign error in the IQ calibration code commit 23399016d9583d799ca98ce443a1410b13c3e96e upstream. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/ar9002_calib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 5fdbb53b47e0..dabafb874c36 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -239,7 +239,7 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) if (qCoff > 15) qCoff = 15; else if (qCoff <= -16) - qCoff = 16; + qCoff = -16; ath_print(common, ATH_DBG_CALIBRATE, "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", -- cgit v1.2.3 From 6554c27728a0b89c6aa5ba78601cd55000b2cc1b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 11 Jul 2010 12:48:41 +0200 Subject: ath9k_hw: fix an off-by-one error in the PDADC boundaries calculation commit 03b4776c408d2f4bf3a5d204e223724d154716d1 upstream. PDADC values were only generated for values surrounding the target index, however not for the target index itself, leading to a minor error in the generated curve. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/eeprom_def.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 7e1ed78d0e64..88219e75e397 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -729,7 +729,7 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, vpdTableI[i][sizeCurrVpdTable - 2]); vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); - if (tgtIndex > maxIndex) { + if (tgtIndex >= maxIndex) { while ((ss <= tgtIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + -- cgit v1.2.3 From a9328d5065468169355a70246bb8ea41d9fc25ef Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 25 Jun 2010 01:26:16 +0200 Subject: ath9k: fix retry count for A-MPDU rate control status reports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 78c4653a2274479547e259e1f416d2b3d04c42a8 upstream. The 'bf_retries' field of the ath_buf structure was used for both software retries (AMPDU subframes) and hardware retries (legacy frames). This led to a wrong retry count being reported for the A-MPDU rate control stats. This patch changes the code to no longer use bf_retries for reporting retry counts, but instead always using the real on-chip retry count from the ath_tx_status. Additionally, if the first subframe of an A-MPDU was not acked, the tx status report is submitted along with the first acked subframe, which may not contain the correct rates in the tx info. This is easily corrected by saving the tx rate info before looping over subframes, and then copying it back once the A-MPDU status report is submitted. In my tests this change improves throughput visibly. Signed-off-by: Felix Fietkau Reported-by: Björn Smedman Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/xmit.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index ac7b88f23d57..2b305ff204f1 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -328,6 +328,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, u32 ba[WME_BA_BMP_SIZE >> 5]; int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; bool rc_update = true; + struct ieee80211_tx_rate rates[4]; skb = bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; @@ -335,6 +336,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, tx_info = IEEE80211_SKB_CB(skb); hw = bf->aphy->hw; + memcpy(rates, tx_info->control.rates, sizeof(rates)); + rcu_read_lock(); /* XXX: use ieee80211_find_sta! */ @@ -375,6 +378,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, txfail = txpending = 0; bf_next = bf->bf_next; + skb = bf->bf_mpdu; + tx_info = IEEE80211_SKB_CB(skb); + if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { /* transmit completion, subframe is * acked by block ack */ @@ -428,6 +434,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, spin_unlock_bh(&txq->axq_lock); if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { + memcpy(tx_info->control.rates, rates, sizeof(rates)); ath_tx_rc_status(bf, ts, nbad, txok, true); rc_update = false; } else { @@ -2050,7 +2057,7 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, tx_info->status.rates[i].idx = -1; } - tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1; + tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; } static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) @@ -2161,7 +2168,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) * This frame is sent out as a single frame. * Use hardware retry status for this frame. */ - bf->bf_retries = ts.ts_longretry; if (ts.ts_status & ATH9K_TXERR_XRETRY) bf->bf_state.bf_type |= BUF_XRETRY; ath_tx_rc_status(bf, &ts, 0, txok, true); @@ -2280,7 +2286,6 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) txok = !(txs.ts_status & ATH9K_TXERR_MASK); if (!bf_isampdu(bf)) { - bf->bf_retries = txs.ts_longretry; if (txs.ts_status & ATH9K_TXERR_XRETRY) bf->bf_state.bf_type |= BUF_XRETRY; ath_tx_rc_status(bf, &txs, 0, txok, true); -- cgit v1.2.3 From caaec883ca2702445d84ff3ee94fe149aeaa95fe Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 7 Jul 2010 19:42:09 +0200 Subject: ath9k: fix a buffer leak in A-MPDU completion commit 73e194639d90594d06d0c10019c0ab4638869135 upstream. When ath_tx_complete_aggr() is called, it's responsible for returning all buffers in the linked list. This was not done when the STA lookup failed, leading to a race condition that could leak a few buffers when a STA just disconnected. Fix this by immediately returning all buffers to the free list in this case. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/xmit.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 2b305ff204f1..191794ec7eb3 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -329,6 +329,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; bool rc_update = true; struct ieee80211_tx_rate rates[4]; + unsigned long flags; skb = bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; @@ -344,6 +345,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, sta = ieee80211_find_sta_by_hw(hw, hdr->addr1); if (!sta) { rcu_read_unlock(); + + spin_lock_irqsave(&sc->tx.txbuflock, flags); + list_splice_tail_init(bf_q, &sc->tx.txbuf); + spin_unlock_irqrestore(&sc->tx.txbuflock, flags); return; } -- cgit v1.2.3 From 793efc368f083e58093fe88e4001375a38cc9a3e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 12 Jul 2010 23:16:34 +0200 Subject: ath9k: another fix for the A-MPDU buffer leak commit 31e79a5954b78fbed15de2c8974d5a2b6019199a upstream. The patch 'ath9k: fix a buffer leak in A-MPDU completion' addressed the issue of running out of buffers/descriptors in the tx path if a STA is deleted while tx status feedback is still pending. The remaining issue is that the skbs of the buffers are not reclaimed, leaving a memory leak. This patch fixes this issue by running the buffers through ath_tx_complete_buf(), ensuring that the pending frames counter is also updated. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/xmit.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 191794ec7eb3..c20a3d6a2e03 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -329,7 +329,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; bool rc_update = true; struct ieee80211_tx_rate rates[4]; - unsigned long flags; skb = bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; @@ -346,9 +345,21 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, if (!sta) { rcu_read_unlock(); - spin_lock_irqsave(&sc->tx.txbuflock, flags); - list_splice_tail_init(bf_q, &sc->tx.txbuf); - spin_unlock_irqrestore(&sc->tx.txbuflock, flags); + INIT_LIST_HEAD(&bf_head); + while (bf) { + bf_next = bf->bf_next; + + bf->bf_state.bf_type |= BUF_XRETRY; + if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) || + !bf->bf_stale || bf_next != NULL) + list_move_tail(&bf->list, &bf_head); + + ath_tx_rc_status(bf, ts, 0, 0, false); + ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, + 0, 0); + + bf = bf_next; + } return; } -- cgit v1.2.3 From 98757bba345d5acde19e736023733cf130675998 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 30 Jun 2010 02:07:48 +0200 Subject: ath9k: fix TSF after reset on AR913x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f860d526eb2939a1c37128900b5af2b6f3ff7f20 upstream. When issuing a reset, the TSF value is lost in the hardware because of the 913x specific cold reset. As with some AR9280 cards, the TSF needs to be preserved in software here. Additionally, there's an issue that frequently prevents a successful TSF write directly after the chip reset. In this case, repeating the TSF write after the initval-writes usually works. This patch detects failed TSF writes and recovers from them, taking into account the delay caused by the initval writes. Signed-off-by: Felix Fietkau Reported-by: Björn Smedman Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/hw.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 079b9638bef5..2feee1ddb50d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1268,7 +1268,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; /* For chips on which RTC reset is done, save TSF before it gets cleared */ - if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) + if (AR_SREV_9100(ah) || + (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))) tsf = ath9k_hw_gettsf64(ah); saveLedState = REG_READ(ah, AR_CFG_LED) & @@ -1300,7 +1301,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, } /* Restore TSF */ - if (tsf && AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) + if (tsf) ath9k_hw_settsf64(ah, tsf); if (AR_SREV_9280_10_OR_LATER(ah)) @@ -1310,6 +1311,17 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (r) return r; + /* + * Some AR91xx SoC devices frequently fail to accept TSF writes + * right after the chip reset. When that happens, write a new + * value after the initvals have been applied, with an offset + * based on measured time difference + */ + if (AR_SREV_9100(ah) && (ath9k_hw_gettsf64(ah) < tsf)) { + tsf += 1500; + ath9k_hw_settsf64(ah, tsf); + } + /* Setup MFP options for CCMP */ if (AR_SREV_9280_20_OR_LATER(ah)) { /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt -- cgit v1.2.3 From b2ca8ba2791b986a96a5d008ea96dc026837b474 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 23 Jul 2010 03:53:16 +0200 Subject: ath9k: fix yet another buffer leak in the tx aggregation code commit 4cee78614cfa046a26c4fbf313d5bbacb3ad8efc upstream. When an aggregation session is being cleaned up, while the tx status for some frames is being processed, the TID is flushed and its buffers are sent out. Unfortunately that left the pending un-acked frames unprocessed, thus leaking buffers. Fix this by reordering the code so that those frames are processed first, before the TID is flushed. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/xmit.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index c20a3d6a2e03..d8dd5034abee 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -510,6 +510,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, bf = bf_next; } + /* prepend un-acked frames to the beginning of the pending frame queue */ + if (!list_empty(&bf_pending)) { + spin_lock_bh(&txq->axq_lock); + list_splice(&bf_pending, &tid->buf_q); + ath_tx_queue_tid(txq, tid); + spin_unlock_bh(&txq->axq_lock); + } + if (tid->state & AGGR_CLEANUP) { if (tid->baw_head == tid->baw_tail) { tid->state &= ~AGGR_ADDBA_COMPLETE; @@ -522,14 +530,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, return; } - /* prepend un-acked frames to the beginning of the pending frame queue */ - if (!list_empty(&bf_pending)) { - spin_lock_bh(&txq->axq_lock); - list_splice(&bf_pending, &tid->buf_q); - ath_tx_queue_tid(txq, tid); - spin_unlock_bh(&txq->axq_lock); - } - rcu_read_unlock(); if (needreset) -- cgit v1.2.3 From 50c144185e4bc848ecdc58cc80113bc48beefdc4 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 11 Jul 2010 12:48:39 +0200 Subject: ath9k_hw: fix antenna diversity on AR9285 commit 601e0cb165e65dc185b31fe7ebd2c0169ea47306 upstream. On AR9285, the antenna switch configuration register uses more than just 16 bits. Because of an arbitrary mask applied to the EEPROM value that stores this configuration, diversity was broken in some cases, leading to a significant degradation in signal strength. Fix this by changing the callback to return a 32 bit value and remove the arbitrary mask. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +- drivers/net/wireless/ath/ath9k/eeprom.h | 2 +- drivers/net/wireless/ath/ath9k/eeprom_4k.c | 4 ++-- drivers/net/wireless/ath/ath9k/eeprom_9287.c | 4 ++-- drivers/net/wireless/ath/ath9k/eeprom_def.c | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 23eb60ea5455..cb4e7daf87f1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -944,7 +944,7 @@ static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah, return 1; } -static u16 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah, +static u32 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah, struct ath9k_channel *chan) { return -EINVAL; diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 21354c15a9a9..5f01a0f40c44 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -669,7 +669,7 @@ struct eeprom_ops { int (*get_eeprom_ver)(struct ath_hw *hw); int (*get_eeprom_rev)(struct ath_hw *hw); u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band); - u16 (*get_eeprom_antenna_cfg)(struct ath_hw *hw, + u32 (*get_eeprom_antenna_cfg)(struct ath_hw *hw, struct ath9k_channel *chan); void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 41a77d1bd439..1576bbbdb2c6 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -1149,13 +1149,13 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, } } -static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah, +static u32 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah, struct ath9k_channel *chan) { struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; struct modal_eep_4k_header *pModal = &eep->modalHeader; - return pModal->antCtrlCommon & 0xFFFF; + return pModal->antCtrlCommon; } static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index b471db5fb82d..2705eb06fa5a 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -1131,13 +1131,13 @@ static u8 ath9k_hw_AR9287_get_num_ant_config(struct ath_hw *ah, return 1; } -static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah, +static u32 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah, struct ath9k_channel *chan) { struct ar9287_eeprom *eep = &ah->eeprom.map9287; struct modal_eep_ar9287_header *pModal = &eep->modalHeader; - return pModal->antCtrlCommon & 0xFFFF; + return pModal->antCtrlCommon; } static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 88219e75e397..54ce34ef1873 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -1437,14 +1437,14 @@ static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, return num_ant_config; } -static u16 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah, +static u32 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah, struct ath9k_channel *chan) { struct ar5416_eeprom_def *eep = &ah->eeprom.def; struct modal_eep_header *pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); - return pModal->antCtrlCommon & 0xFFFF; + return pModal->antCtrlCommon; } static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) -- cgit v1.2.3 From 5806c0444a387eb4cfecaec74660427f15dfd570 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 29 Jul 2010 11:37:41 +0200 Subject: iwlwifi: fix scan abort commit d28232b461b8d54b09e59325dbac8b0913ce2049 upstream. Fix possible double priv->mutex lock introduced by commit a69b03e941abae00380fc6bc1877fb797a1b31e6 "iwlwifi: cancel scan watchdog in iwl_bg_abort_scan" . We can not call cancel_delayed_work_sync(&priv->scan_check) with priv->mutex locked because workqueue function iwl_bg_scan_check() take that lock internally. We do not need to synchronize when canceling priv->scan_check work. We can avoid races (sending double abort command or send no command at all) using STATUS_SCAN_ABORT bit. Moreover current iwl_bg_scan_check() code seems to be broken, as we should not send abort commands when currently aborting. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-scan.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 386c5f96eff8..e1af9fd5ac3a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -420,11 +420,10 @@ void iwl_bg_scan_check(struct work_struct *data) return; mutex_lock(&priv->mutex); - if (test_bit(STATUS_SCANNING, &priv->status) || - test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_SCAN(priv, "Scan completion watchdog resetting " - "adapter (%dms)\n", - jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); + if (test_bit(STATUS_SCANNING, &priv->status) && + !test_bit(STATUS_SCAN_ABORTING, &priv->status)) { + IWL_DEBUG_SCAN(priv, "Scan completion watchdog (%dms)\n", + jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) iwl_send_scan_abort(priv); @@ -489,12 +488,11 @@ void iwl_bg_abort_scan(struct work_struct *work) !test_bit(STATUS_GEO_CONFIGURED, &priv->status)) return; - mutex_lock(&priv->mutex); - - cancel_delayed_work_sync(&priv->scan_check); - set_bit(STATUS_SCAN_ABORTING, &priv->status); - iwl_send_scan_abort(priv); + cancel_delayed_work(&priv->scan_check); + mutex_lock(&priv->mutex); + if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) + iwl_send_scan_abort(priv); mutex_unlock(&priv->mutex); } EXPORT_SYMBOL(iwl_bg_abort_scan); -- cgit v1.2.3 From 433a64e4233a9dd3775b1e248a01d88a3a038592 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 14 May 2010 22:08:58 -0500 Subject: ssb: Handle alternate SSPROM location commit 9d1ac34ec3a67713308ae0883c3359c557f14d17 upstream. In kernel Bugzilla #15825 (2 users), in a wireless mailing list thread (http://lists.infradead.org/pipermail/b43-dev/2010-May/000124.html), and on a netbook owned by John Linville (http://marc.info/?l=linux-wireless&m=127230751408818&w=4), there are reports of ssb failing to detect an SPROM at the normal location. After studying the MMIO trace dump for the Broadcom wl driver, it was determined that the affected boxes had a relocated SPROM. This patch fixes all systems that have reported this problem. Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/ssb/driver_chipcommon.c | 1 + drivers/ssb/pci.c | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index 59ae76bace14..d9c7e54de100 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c @@ -235,6 +235,7 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc) return; /* We don't have a ChipCommon */ if (cc->dev->id.revision >= 11) cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); + ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status); ssb_pmu_init(cc); chipco_powercontrol_init(cc); ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index 6dcda86be6eb..6e88d2b603b4 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c @@ -626,11 +626,22 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, return -ENODEV; } if (bus->chipco.dev) { /* can be unavailible! */ - bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ? - SSB_SPROM_BASE1 : SSB_SPROM_BASE31; + /* + * get SPROM offset: SSB_SPROM_BASE1 except for + * chipcommon rev >= 31 or chip ID is 0x4312 and + * chipcommon status & 3 == 2 + */ + if (bus->chipco.dev->id.revision >= 31) + bus->sprom_offset = SSB_SPROM_BASE31; + else if (bus->chip_id == 0x4312 && + (bus->chipco.status & 0x03) == 2) + bus->sprom_offset = SSB_SPROM_BASE31; + else + bus->sprom_offset = SSB_SPROM_BASE1; } else { bus->sprom_offset = SSB_SPROM_BASE1; } + ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset); buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); if (!buf) -- cgit v1.2.3 From 89b15fbbcb5e77845ea1d8e96e0973caa0749fed Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 12 Jul 2010 14:46:43 +0200 Subject: cfg80211: ignore spurious deauth commit 643f82e32f14faf0d0944c804203a6681b6b0a1e upstream. Ever since mac80211/drivers are no longer fully in charge of keeping track of the auth status, trying to make them do so will fail. Instead of warning and reporting the deauthentication to userspace, cfg80211 must simply ignore it so that spurious deauthentications, e.g. before starting authentication, aren't seen by userspace as actual deauthentications. Reported-by: Paul Stewart Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/wireless/mlme.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 48ead6f0426d..ef17fcf85092 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -44,10 +44,10 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len) } } - WARN_ON(!done); - - nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); - cfg80211_sme_rx_auth(dev, buf, len); + if (done) { + nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); + cfg80211_sme_rx_auth(dev, buf, len); + } wdev_unlock(wdev); } -- cgit v1.2.3 From bfcd88d2b16638f74957a78c787e0284d7080284 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 13 Jul 2010 10:55:38 +0200 Subject: cfg80211: don't get expired BSSes commit ccb6c1360f8dd43303c659db718e7e0b24175db5 upstream. When kernel-internal users use cfg80211_get_bss() to get a reference to a BSS struct, they may end up getting one that would have been removed from the list if there had been any userspace access to the list. This leads to inconsistencies and problems. Fix it by making cfg80211_get_bss() ignore BSSes that cfg80211_bss_expire() would remove. Fixes http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2180 Reported-by: Jiajia Zheng Tested-by: Jiajia Zheng Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/wireless/scan.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 58401d246bda..5ca8c7180141 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -275,6 +275,7 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, { struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy); struct cfg80211_internal_bss *bss, *res = NULL; + unsigned long now = jiffies; spin_lock_bh(&dev->bss_lock); @@ -283,6 +284,10 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, continue; if (channel && bss->pub.channel != channel) continue; + /* Don't get expired BSS structs */ + if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) && + !atomic_read(&bss->hold)) + continue; if (is_bss(&bss->pub, bssid, ssid, ssid_len)) { res = bss; kref_get(&res->ref); -- cgit v1.2.3 From 1a0528f57734493e588229266130c247a8e26ac2 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 21 Jun 2010 17:14:07 -0400 Subject: mac80211: avoid scheduling while atomic in mesh_rx_plink_frame commit c937019761a758f2749b1f3a032b7a91fb044753 upstream. While mesh_rx_plink_frame holds sta->lock... mesh_rx_plink_frame -> mesh_plink_inc_estab_count -> ieee80211_bss_info_change_notify ...but ieee80211_bss_info_change_notify is allowed to sleep. A driver taking advantage of that allowance can cause a scheduling while atomic bug. Similar paths exist for mesh_plink_dec_estab_count, so work around those as well. http://bugzilla.kernel.org/show_bug.cgi?id=16099 Also, correct a minor kerneldoc comment error (mismatched function names). Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/mesh_plink.c | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 3cd5f7b5d693..ea13a80a476c 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -65,7 +65,6 @@ void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) { atomic_inc(&sdata->u.mesh.mshstats.estab_plinks); mesh_accept_plinks_update(sdata); - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); } static inline @@ -73,7 +72,6 @@ void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) { atomic_dec(&sdata->u.mesh.mshstats.estab_plinks); mesh_accept_plinks_update(sdata); - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); } /** @@ -115,7 +113,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, } /** - * mesh_plink_deactivate - deactivate mesh peer link + * __mesh_plink_deactivate - deactivate mesh peer link * * @sta: mesh peer link to deactivate * @@ -123,18 +121,23 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, * * Locking: the caller must hold sta->lock */ -static void __mesh_plink_deactivate(struct sta_info *sta) +static bool __mesh_plink_deactivate(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; + bool deactivated = false; - if (sta->plink_state == PLINK_ESTAB) + if (sta->plink_state == PLINK_ESTAB) { mesh_plink_dec_estab_count(sdata); + deactivated = true; + } sta->plink_state = PLINK_BLOCKED; mesh_path_flush_by_nexthop(sta); + + return deactivated; } /** - * __mesh_plink_deactivate - deactivate mesh peer link + * mesh_plink_deactivate - deactivate mesh peer link * * @sta: mesh peer link to deactivate * @@ -142,9 +145,15 @@ static void __mesh_plink_deactivate(struct sta_info *sta) */ void mesh_plink_deactivate(struct sta_info *sta) { + struct ieee80211_sub_if_data *sdata = sta->sdata; + bool deactivated; + spin_lock_bh(&sta->lock); - __mesh_plink_deactivate(sta); + deactivated = __mesh_plink_deactivate(sta); spin_unlock_bh(&sta->lock); + + if (deactivated) + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); } static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, @@ -381,10 +390,16 @@ int mesh_plink_open(struct sta_info *sta) void mesh_plink_block(struct sta_info *sta) { + struct ieee80211_sub_if_data *sdata = sta->sdata; + bool deactivated; + spin_lock_bh(&sta->lock); - __mesh_plink_deactivate(sta); + deactivated = __mesh_plink_deactivate(sta); sta->plink_state = PLINK_BLOCKED; spin_unlock_bh(&sta->lock); + + if (deactivated) + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); } @@ -397,6 +412,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m enum plink_event event; enum plink_frame_type ftype; size_t baselen; + bool deactivated; u8 ie_len; u8 *baseaddr; __le16 plid, llid, reason; @@ -651,8 +667,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m case CNF_ACPT: del_timer(&sta->plink_timer); sta->plink_state = PLINK_ESTAB; - mesh_plink_inc_estab_count(sdata); spin_unlock_bh(&sta->lock); + mesh_plink_inc_estab_count(sdata); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); mpl_dbg("Mesh plink with %pM ESTABLISHED\n", sta->sta.addr); break; @@ -684,8 +701,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m case OPN_ACPT: del_timer(&sta->plink_timer); sta->plink_state = PLINK_ESTAB; - mesh_plink_inc_estab_count(sdata); spin_unlock_bh(&sta->lock); + mesh_plink_inc_estab_count(sdata); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); mpl_dbg("Mesh plink with %pM ESTABLISHED\n", sta->sta.addr); mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, @@ -702,11 +720,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m case CLS_ACPT: reason = cpu_to_le16(MESH_CLOSE_RCVD); sta->reason = reason; - __mesh_plink_deactivate(sta); + deactivated = __mesh_plink_deactivate(sta); sta->plink_state = PLINK_HOLDING; llid = sta->llid; mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); spin_unlock_bh(&sta->lock); + if (deactivated) + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid, reason); break; -- cgit v1.2.3 From 5232dfac1ac008b5a4df815a5256776913dfa025 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 4 Aug 2010 16:59:14 +0100 Subject: CRED: Fix RCU warning due to previous patch fixing __task_cred()'s checks commit 694f690d27dadccc8cb9d90532e76593b61fe098 upstream. Commit 8f92054e7ca1 ("CRED: Fix __task_cred()'s lockdep check and banner comment") fixed the lockdep checks on __task_cred(). This has shown up a place in the signalling code where a lock should be held - namely that check_kill_permission() requires its callers to hold the RCU lock. Fix group_send_sig_info() to get the RCU read lock around its call to check_kill_permission(). Without this patch, the following warning can occur: =================================================== [ INFO: suspicious rcu_dereference_check() usage. ] --------------------------------------------------- kernel/signal.c:660 invoked rcu_dereference_check() without protection! ... Reported-by: Tetsuo Handa Signed-off-by: David Howells Acked-by: Oleg Nesterov Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/signal.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel/signal.c b/kernel/signal.c index 906ae5a1779c..bded65187780 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -637,7 +637,7 @@ static inline bool si_fromuser(const struct siginfo *info) /* * Bad permissions for sending the signal - * - the caller must hold at least the RCU read lock + * - the caller must hold the RCU read lock */ static int check_kill_permission(int sig, struct siginfo *info, struct task_struct *t) @@ -1127,11 +1127,14 @@ struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long /* * send signal info to all the members of a group - * - the caller must hold the RCU read lock at least */ int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) { - int ret = check_kill_permission(sig, info, p); + int ret; + + rcu_read_lock(); + ret = check_kill_permission(sig, info, p); + rcu_read_unlock(); if (!ret && sig) ret = do_send_sig_info(sig, info, p, true); -- cgit v1.2.3 From efe5d7f1ad582cafc68624f39ba720e12bcddb20 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 12 Mar 2010 16:14:42 -0600 Subject: SCSI: enclosure: fix error path - actually return ERR_PTR() on error commit a91c1be21704113b023919826c6d531da46656ef upstream. we also need to clean up and free the cdev. Reported-by: Jani Nikula Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/misc/enclosure.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c index 48c84a58163e..00e5fcac8fdf 100644 --- a/drivers/misc/enclosure.c +++ b/drivers/misc/enclosure.c @@ -285,8 +285,11 @@ enclosure_component_register(struct enclosure_device *edev, cdev->groups = enclosure_groups; err = device_register(cdev); - if (err) - ERR_PTR(err); + if (err) { + ecomp->number = -1; + put_device(cdev); + return ERR_PTR(err); + } return ecomp; } -- cgit v1.2.3 From a1e0ea5d94314a56340859097442673890b04ef5 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 12 Jul 2010 11:49:59 -0700 Subject: xen: drop xen_sched_clock in favour of using plain wallclock time commit 8a22b9996b001c88f2bfb54c6de6a05fc39e177a upstream. xen_sched_clock only counts unstolen time. In principle this should be useful to the Linux scheduler so that it knows how much time a process actually consumed. But in practice this doesn't work very well as the scheduler expects the sched_clock time to be synchronized between cpus. It also uses sched_clock to measure the time a task spends sleeping, in which case "unstolen time" isn't meaningful. So just use plain xen_clocksource_read to return wallclock nanoseconds for sched_clock. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/enlighten.c | 2 +- arch/x86/xen/time.c | 39 --------------------------------------- 2 files changed, 1 insertion(+), 40 deletions(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 65d8d79b46a8..27dff06d9793 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -927,7 +927,7 @@ static const struct pv_init_ops xen_init_ops __initdata = { }; static const struct pv_time_ops xen_time_ops __initdata = { - .sched_clock = xen_sched_clock, + .sched_clock = xen_clocksource_read, }; static const struct pv_cpu_ops xen_cpu_ops __initdata = { diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index b3c6c59ed302..a86df42e46ad 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -155,45 +155,6 @@ static void do_stolen_accounting(void) account_idle_ticks(ticks); } -/* - * Xen sched_clock implementation. Returns the number of unstolen - * nanoseconds, which is nanoseconds the VCPU spent in RUNNING+BLOCKED - * states. - */ -unsigned long long xen_sched_clock(void) -{ - struct vcpu_runstate_info state; - cycle_t now; - u64 ret; - s64 offset; - - /* - * Ideally sched_clock should be called on a per-cpu basis - * anyway, so preempt should already be disabled, but that's - * not current practice at the moment. - */ - preempt_disable(); - - now = xen_clocksource_read(); - - get_runstate_snapshot(&state); - - WARN_ON(state.state != RUNSTATE_running); - - offset = now - state.state_entry_time; - if (offset < 0) - offset = 0; - - ret = state.time[RUNSTATE_blocked] + - state.time[RUNSTATE_running] + - offset; - - preempt_enable(); - - return ret; -} - - /* Get the TSC speed from Xen */ unsigned long xen_tsc_khz(void) { -- cgit v1.2.3 From 37aa5ce0ed1e1535c22fc3d37f36e39dd82e80b1 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 4 Aug 2010 11:40:00 -0400 Subject: drm/radeon: add new pci ids commit 1297c05a8dfb568c689f057d51a65eebe5ddc86f upstream. New evergreen and r7xx ids. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- include/drm/drm_pciids.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 2d428b088cc8..3a9940ef728b 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -146,6 +146,8 @@ {0x1002, 0x6888, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6889, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x688A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x688C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x688D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6898, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6899, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x689c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HEMLOCK|RADEON_NEW_MEMMAP}, \ @@ -161,6 +163,7 @@ {0x1002, 0x68be, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68c1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x68c7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68c8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68c9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \ @@ -174,6 +177,7 @@ {0x1002, 0x68e8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68e9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68f1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x68f2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68f8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68f9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68fe, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ @@ -314,6 +318,7 @@ {0x1002, 0x9456, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \ {0x1002, 0x945A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x945B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x945E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \ {0x1002, 0x946A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ @@ -324,6 +329,7 @@ {0x1002, 0x9487, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9488, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9489, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x948A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x948F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9490, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9491, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ @@ -366,6 +372,7 @@ {0x1002, 0x9553, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9555, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9557, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x955f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9580, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9581, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9583, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ -- cgit v1.2.3 From 1e4966cc558d6aac892abeed6434591348103dff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Thu, 8 Jul 2010 12:43:28 +1000 Subject: drm/radeon: fall back to GTT if bo creation/validation in VRAM fails. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit e376573f7267390f4e1bdc552564b6fb913bce76 upstream. This fixes a problem where on low VRAM cards we'd run out of space for validation. [airlied: Tested on my M7, Thinkpad T42, compiz works with no problems.] Signed-off-by: Michel Dänzer Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_object.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index d5b9373ce06c..d33b6c91ceda 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -110,6 +110,7 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj, bo->surface_reg = -1; INIT_LIST_HEAD(&bo->list); +retry: radeon_ttm_placement_from_domain(bo, domain); /* Kernel allocation are uninterruptible */ mutex_lock(&rdev->vram_mutex); @@ -118,10 +119,15 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj, &radeon_ttm_bo_destroy); mutex_unlock(&rdev->vram_mutex); if (unlikely(r != 0)) { - if (r != -ERESTARTSYS) + if (r != -ERESTARTSYS) { + if (domain == RADEON_GEM_DOMAIN_VRAM) { + domain |= RADEON_GEM_DOMAIN_GTT; + goto retry; + } dev_err(rdev->dev, "object_init failed for (%lu, 0x%08X)\n", size, domain); + } return r; } *bo_ptr = bo; @@ -321,6 +327,7 @@ int radeon_bo_list_validate(struct list_head *head) { struct radeon_bo_list *lobj; struct radeon_bo *bo; + u32 domain; int r; list_for_each_entry(lobj, head, list) { @@ -333,17 +340,19 @@ int radeon_bo_list_validate(struct list_head *head) list_for_each_entry(lobj, head, list) { bo = lobj->bo; if (!bo->pin_count) { - if (lobj->wdomain) { - radeon_ttm_placement_from_domain(bo, - lobj->wdomain); - } else { - radeon_ttm_placement_from_domain(bo, - lobj->rdomain); - } + domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain; + + retry: + radeon_ttm_placement_from_domain(bo, domain); r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false, false); - if (unlikely(r)) + if (unlikely(r)) { + if (r != -ERESTARTSYS && domain == RADEON_GEM_DOMAIN_VRAM) { + domain |= RADEON_GEM_DOMAIN_GTT; + goto retry; + } return r; + } } lobj->gpu_offset = radeon_bo_gpu_offset(bo); lobj->tiling_flags = bo->tiling_flags; -- cgit v1.2.3 From 44437579efca258e3c4a09f59838c8f933611990 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 26 Jul 2010 18:51:53 -0400 Subject: drm/radeon/kms/r7xx: add workaround for hw issue with HDP flush commit 812d046915f48236657f02c06d7dc47140e9ceda upstream. Use of HDP_*_COHERENCY_FLUSH_CNTL can cause a hang in certain situations. Add workaround. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/r600.c | 24 ++++++++++++++++++++++-- drivers/gpu/drm/radeon/r600d.h | 1 + drivers/gpu/drm/radeon/rv770.c | 5 ++++- drivers/gpu/drm/radeon/rv770d.h | 1 + 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index e100f69faeec..bb3de0158460 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -869,7 +869,17 @@ void r600_pcie_gart_tlb_flush(struct radeon_device *rdev) u32 tmp; /* flush hdp cache so updates hit vram */ - WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); + if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) { + void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; + u32 tmp; + + /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read + * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL + */ + WREG32(HDP_DEBUG1, 0); + tmp = readl((void __iomem *)ptr); + } else + WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); WREG32(VM_CONTEXT0_INVALIDATION_LOW_ADDR, rdev->mc.gtt_start >> 12); WREG32(VM_CONTEXT0_INVALIDATION_HIGH_ADDR, (rdev->mc.gtt_end - 1) >> 12); @@ -3512,5 +3522,15 @@ int r600_debugfs_mc_info_init(struct radeon_device *rdev) */ void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo) { - WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); + /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read + * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL + */ + if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) { + void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; + u32 tmp; + + WREG32(HDP_DEBUG1, 0); + tmp = readl((void __iomem *)ptr); + } else + WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); } diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 59c1f8793e60..84bc28e7a399 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -245,6 +245,7 @@ #define HDP_NONSURFACE_SIZE 0x2C0C #define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0 #define HDP_TILING_CONFIG 0x2F3C +#define HDP_DEBUG1 0x2F34 #define MC_VM_AGP_TOP 0x2184 #define MC_VM_AGP_BOT 0x2188 diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index b7fd82064922..1d6fb79de27e 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -189,7 +189,10 @@ static void rv770_mc_program(struct radeon_device *rdev) WREG32((0x2c20 + j), 0x00000000); WREG32((0x2c24 + j), 0x00000000); } - WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0); + /* r7xx hw bug. Read from HDP_DEBUG1 rather + * than writing to HDP_REG_COHERENCY_FLUSH_CNTL + */ + tmp = RREG32(HDP_DEBUG1); rv515_mc_stop(rdev, &save); if (r600_mc_wait_for_idle(rdev)) { diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h index 9506f8cb99e0..6111a022f76c 100644 --- a/drivers/gpu/drm/radeon/rv770d.h +++ b/drivers/gpu/drm/radeon/rv770d.h @@ -128,6 +128,7 @@ #define HDP_NONSURFACE_SIZE 0x2C0C #define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0 #define HDP_TILING_CONFIG 0x2F3C +#define HDP_DEBUG1 0x2F34 #define MC_SHARED_CHMAP 0x2004 #define NOOFCHAN_SHIFT 12 -- cgit v1.2.3 From c1899005b1dc135bf42198ce65cfb52c22f5bdf9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 2 Aug 2010 12:13:46 -0400 Subject: drm/radeon/kms: handle the case of no active displays properly in the bandwidth code commit e06b14ee91a2ddefc9a67443a6cd8ee0fa800115 upstream. Logic was: if (mode0 && mode1) else if (mode0) else Should be: if (mode0 && mode1) else if (mode0) else if (mode1) Otherwise we may end up calculating the priority regs with unitialized values. Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=16492 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/rs690.c | 27 +++++++++------------------ drivers/gpu/drm/radeon/rv515.c | 23 +++++++++-------------- 2 files changed, 18 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index ce4ecbe10816..76c768b3796b 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -398,7 +398,9 @@ void rs690_bandwidth_update(struct radeon_device *rdev) struct drm_display_mode *mode1 = NULL; struct rs690_watermark wm0; struct rs690_watermark wm1; - u32 tmp, d1mode_priority_a_cnt, d2mode_priority_a_cnt; + u32 tmp; + u32 d1mode_priority_a_cnt = S_006548_D1MODE_PRIORITY_A_OFF(1); + u32 d2mode_priority_a_cnt = S_006548_D1MODE_PRIORITY_A_OFF(1); fixed20_12 priority_mark02, priority_mark12, fill_rate; fixed20_12 a, b; @@ -495,10 +497,6 @@ void rs690_bandwidth_update(struct radeon_device *rdev) d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1); d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1); } - WREG32(R_006548_D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt); - WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt); - WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt); - WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt); } else if (mode0) { if (dfixed_trunc(wm0.dbpp) > 64) a.full = dfixed_mul(wm0.dbpp, wm0.num_line_pair); @@ -528,13 +526,7 @@ void rs690_bandwidth_update(struct radeon_device *rdev) d1mode_priority_a_cnt = dfixed_trunc(priority_mark02); if (rdev->disp_priority == 2) d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1); - WREG32(R_006548_D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt); - WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt); - WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, - S_006D48_D2MODE_PRIORITY_A_OFF(1)); - WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, - S_006D4C_D2MODE_PRIORITY_B_OFF(1)); - } else { + } else if (mode1) { if (dfixed_trunc(wm1.dbpp) > 64) a.full = dfixed_mul(wm1.dbpp, wm1.num_line_pair); else @@ -563,13 +555,12 @@ void rs690_bandwidth_update(struct radeon_device *rdev) d2mode_priority_a_cnt = dfixed_trunc(priority_mark12); if (rdev->disp_priority == 2) d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1); - WREG32(R_006548_D1MODE_PRIORITY_A_CNT, - S_006548_D1MODE_PRIORITY_A_OFF(1)); - WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, - S_00654C_D1MODE_PRIORITY_B_OFF(1)); - WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt); - WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt); } + + WREG32(R_006548_D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt); + WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt); + WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt); + WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt); } uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg) diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 0c9c169a6852..7e4fbdb89fe9 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -925,7 +925,9 @@ void rv515_bandwidth_avivo_update(struct radeon_device *rdev) struct drm_display_mode *mode1 = NULL; struct rv515_watermark wm0; struct rv515_watermark wm1; - u32 tmp, d1mode_priority_a_cnt, d2mode_priority_a_cnt; + u32 tmp; + u32 d1mode_priority_a_cnt = MODE_PRIORITY_OFF; + u32 d2mode_priority_a_cnt = MODE_PRIORITY_OFF; fixed20_12 priority_mark02, priority_mark12, fill_rate; fixed20_12 a, b; @@ -999,10 +1001,6 @@ void rv515_bandwidth_avivo_update(struct radeon_device *rdev) d1mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON; d2mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON; } - WREG32(D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt); - WREG32(D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt); - WREG32(D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt); - WREG32(D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt); } else if (mode0) { if (dfixed_trunc(wm0.dbpp) > 64) a.full = dfixed_div(wm0.dbpp, wm0.num_line_pair); @@ -1032,11 +1030,7 @@ void rv515_bandwidth_avivo_update(struct radeon_device *rdev) d1mode_priority_a_cnt = dfixed_trunc(priority_mark02); if (rdev->disp_priority == 2) d1mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON; - WREG32(D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt); - WREG32(D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt); - WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF); - WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF); - } else { + } else if (mode1) { if (dfixed_trunc(wm1.dbpp) > 64) a.full = dfixed_div(wm1.dbpp, wm1.num_line_pair); else @@ -1065,11 +1059,12 @@ void rv515_bandwidth_avivo_update(struct radeon_device *rdev) d2mode_priority_a_cnt = dfixed_trunc(priority_mark12); if (rdev->disp_priority == 2) d2mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON; - WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF); - WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF); - WREG32(D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt); - WREG32(D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt); } + + WREG32(D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt); + WREG32(D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt); + WREG32(D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt); + WREG32(D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt); } void rv515_bandwidth_update(struct radeon_device *rdev) -- cgit v1.2.3 From 5078304217e1e87bc7ffe8d7a4076e4cb0c0a318 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Jul 2010 08:45:04 +0100 Subject: drm/i915: Unset cursor if out-of-bounds upon mode change (v4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit cda4b7d3a5b1dcbc0d8e7bad52134347798e9047 upstream. The docs warn that to position the cursor such that no part of it is visible on the pipe is an undefined operation. Avoid such circumstances upon changing the mode, or at any other time, by unsetting the cursor if it moves out of bounds. "For normal high resolution display modes, the cursor must have at least a single pixel positioned over the active screen.” (p143, p148 of the hardware registers docs). Fixes: Bug 24748 - [965G] Graphics crashes when resolution is changed with KMS enabled https://bugs.freedesktop.org/show_bug.cgi?id=24748 v2: Only update the cursor registers if they change. v3: Fix the unsigned comparision of x,y against width,height. v4: Always set CUR.BASE or else the cursor may become corrupt. Signed-off-by: Chris Wilson Reported-by: Christian Eggers Cc: Christopher James Halse Rogers Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 144 ++++++++++++++++++++++------------- drivers/gpu/drm/i915/intel_drv.h | 8 +- 2 files changed, 99 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5e21b3119824..8a84306292e0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -42,6 +42,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type); static void intel_update_watermarks(struct drm_device *dev); static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule); +static void intel_crtc_update_cursor(struct drm_crtc *crtc); typedef struct { /* given values */ @@ -3403,6 +3404,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, return -EINVAL; } + /* Ensure that the cursor is valid for the new mode before changing... */ + intel_crtc_update_cursor(crtc); + if (is_lvds && dev_priv->lvds_downclock_avail) { has_reduced_clock = limit->find_pll(limit, crtc, dev_priv->lvds_downclock, @@ -3939,6 +3943,85 @@ void intel_crtc_load_lut(struct drm_crtc *crtc) } } +/* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ +static void intel_crtc_update_cursor(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + int x = intel_crtc->cursor_x; + int y = intel_crtc->cursor_y; + uint32_t base, pos; + bool visible; + + pos = 0; + + if (crtc->fb) { + base = intel_crtc->cursor_addr; + if (x > (int) crtc->fb->width) + base = 0; + + if (y > (int) crtc->fb->height) + base = 0; + } else + base = 0; + + if (x < 0) { + if (x + intel_crtc->cursor_width < 0) + base = 0; + + pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; + x = -x; + } + pos |= x << CURSOR_X_SHIFT; + + if (y < 0) { + if (y + intel_crtc->cursor_height < 0) + base = 0; + + pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; + y = -y; + } + pos |= y << CURSOR_Y_SHIFT; + + visible = base != 0; + if (!visible && !intel_crtc->cursor_visble) + return; + + I915_WRITE(pipe == 0 ? CURAPOS : CURBPOS, pos); + if (intel_crtc->cursor_visble != visible) { + uint32_t cntl = I915_READ(pipe == 0 ? CURACNTR : CURBCNTR); + if (base) { + /* Hooray for CUR*CNTR differences */ + if (IS_MOBILE(dev) || IS_I9XX(dev)) { + cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); + cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; + cntl |= pipe << 28; /* Connect to correct pipe */ + } else { + cntl &= ~(CURSOR_FORMAT_MASK); + cntl |= CURSOR_ENABLE; + cntl |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE; + } + } else { + if (IS_MOBILE(dev) || IS_I9XX(dev)) { + cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); + cntl |= CURSOR_MODE_DISABLE; + } else { + cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE); + } + } + I915_WRITE(pipe == 0 ? CURACNTR : CURBCNTR, cntl); + + intel_crtc->cursor_visble = visible; + } + /* and commit changes on next vblank */ + I915_WRITE(pipe == 0 ? CURABASE : CURBBASE, base); + + if (visible) + intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj); +} + static int intel_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, uint32_t handle, @@ -3949,11 +4032,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_gem_object *bo; struct drm_i915_gem_object *obj_priv; - int pipe = intel_crtc->pipe; - uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; - uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; - uint32_t temp = I915_READ(control); - size_t addr; + uint32_t addr; int ret; DRM_DEBUG_KMS("\n"); @@ -3961,12 +4040,6 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, /* if we want to turn off the cursor ignore width and height */ if (!handle) { DRM_DEBUG_KMS("cursor off\n"); - if (IS_MOBILE(dev) || IS_I9XX(dev)) { - temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); - temp |= CURSOR_MODE_DISABLE; - } else { - temp &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE); - } addr = 0; bo = NULL; mutex_lock(&dev->struct_mutex); @@ -4008,7 +4081,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, addr = obj_priv->gtt_offset; } else { - ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1); + ret = i915_gem_attach_phys_object(dev, bo, + (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1); if (ret) { DRM_ERROR("failed to attach phys object\n"); goto fail_locked; @@ -4019,21 +4093,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, if (!IS_I9XX(dev)) I915_WRITE(CURSIZE, (height << 12) | width); - /* Hooray for CUR*CNTR differences */ - if (IS_MOBILE(dev) || IS_I9XX(dev)) { - temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); - temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; - temp |= (pipe << 28); /* Connect to correct pipe */ - } else { - temp &= ~(CURSOR_FORMAT_MASK); - temp |= CURSOR_ENABLE; - temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE; - } - finish: - I915_WRITE(control, temp); - I915_WRITE(base, addr); - if (intel_crtc->cursor_bo) { if (dev_priv->info->cursor_needs_physical) { if (intel_crtc->cursor_bo != bo) @@ -4047,6 +4107,10 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, intel_crtc->cursor_addr = addr; intel_crtc->cursor_bo = bo; + intel_crtc->cursor_width = width; + intel_crtc->cursor_height = height; + + intel_crtc_update_cursor(crtc); return 0; fail_unpin: @@ -4060,34 +4124,12 @@ fail: static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) { - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_framebuffer *intel_fb; - int pipe = intel_crtc->pipe; - uint32_t temp = 0; - uint32_t adder; - - if (crtc->fb) { - intel_fb = to_intel_framebuffer(crtc->fb); - intel_mark_busy(dev, intel_fb->obj); - } - - if (x < 0) { - temp |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; - x = -x; - } - if (y < 0) { - temp |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; - y = -y; - } - temp |= x << CURSOR_X_SHIFT; - temp |= y << CURSOR_Y_SHIFT; + intel_crtc->cursor_x = x; + intel_crtc->cursor_y = y; - adder = intel_crtc->cursor_addr; - I915_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); - I915_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder); + intel_crtc_update_cursor(crtc); return 0; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 2f7970be9051..2702652337d6 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -143,8 +143,6 @@ struct intel_crtc { struct drm_crtc base; enum pipe pipe; enum plane plane; - struct drm_gem_object *cursor_bo; - uint32_t cursor_addr; u8 lut_r[256], lut_g[256], lut_b[256]; int dpms_mode; bool busy; /* is scanout buffer being updated frequently? */ @@ -153,6 +151,12 @@ struct intel_crtc { struct intel_overlay *overlay; struct intel_unpin_work *unpin_work; int fdi_lanes; + + struct drm_gem_object *cursor_bo; + uint32_t cursor_addr; + int16_t cursor_x, cursor_y; + int16_t cursor_width, cursor_height; + bool cursor_visble; }; #define to_intel_crtc(x) container_of(x, struct intel_crtc, base) -- cgit v1.2.3 From 4060b482bfb832715e43695e124031bede63be75 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 12 Jul 2010 19:35:38 +0100 Subject: drm/i915: Check overlay stride errata for i830 and i845 commit a1efd14a99483a4fb9308902397ed86b69454c99 upstream. Apparently i830 and i845 cannot handle any stride that is not a multiple of 256, unlike their brethren which do support 64 byte aligned strides. Signed-off-by: Chris Wilson Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_overlay.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index d7ad5139d17c..fe05ba27440a 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -958,7 +958,7 @@ static int check_overlay_src(struct drm_device *dev, || rec->src_width < N_HORIZ_Y_TAPS*4) return -EINVAL; - /* check alingment constrains */ + /* check alignment constraints */ switch (rec->flags & I915_OVERLAY_TYPE_MASK) { case I915_OVERLAY_RGB: /* not implemented */ @@ -990,7 +990,10 @@ static int check_overlay_src(struct drm_device *dev, return -EINVAL; /* stride checking */ - stride_mask = 63; + if (IS_I830(dev) || IS_845G(dev)) + stride_mask = 255; + else + stride_mask = 63; if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask) return -EINVAL; -- cgit v1.2.3 From 3f3ed15762e959843793763db4aac37cc9bd9644 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 10 Aug 2010 11:37:31 -0700 Subject: Linux 2.6.35.1 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 141da26fda4b..0b9c76386b96 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 35 -EXTRAVERSION = +EXTRAVERSION = .1 NAME = Sheep on Meth # *DOCUMENTATION* -- cgit v1.2.3 From 94f6da84e80c01e655df88479d7b57a6d89965f2 Mon Sep 17 00:00:00 2001 From: Alok Kataria Date: Mon, 2 Aug 2010 16:10:37 -0700 Subject: x86, vmware: Preset lpj values when on VMware. commit 9f242dc10e0c3c1eb32d8c83c18650a35fd7f80d upstream. When running on VMware's platform, we have seen situations where the AP's try to calibrate the lpj values and fail to get good calibration runs becasue of timing issues. As a result delays don't work correctly on all cpus. The solutions is to set preset_lpj value based on the current tsc frequency value. This is similar to what KVM does as well. Signed-off-by: Alok N Kataria LKML-Reference: <1280790637.14933.29.camel@ank32.eng.vmware.com> Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/vmware.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index b9d1ff588445..227b0448960d 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -51,7 +51,7 @@ static inline int __vmware_platform(void) static unsigned long vmware_get_tsc_khz(void) { - uint64_t tsc_hz; + uint64_t tsc_hz, lpj; uint32_t eax, ebx, ecx, edx; VMWARE_PORT(GETHZ, eax, ebx, ecx, edx); @@ -62,6 +62,13 @@ static unsigned long vmware_get_tsc_khz(void) printk(KERN_INFO "TSC freq read from hypervisor : %lu.%03lu MHz\n", (unsigned long) tsc_hz / 1000, (unsigned long) tsc_hz % 1000); + + if (!preset_lpj) { + lpj = ((u64)tsc_hz * 1000); + do_div(lpj, HZ); + preset_lpj = lpj; + } + return tsc_hz; } -- cgit v1.2.3 From da2756b5e1129785dc107a90fcb729728c427c50 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 20 Jul 2010 16:20:01 +0200 Subject: ata_piix: fix locking around SIDPR access commit 213373cf974fe69e78ec894b07f45ae2f5a3a078 upstream. SIDPR window registers are shared across ports and as each access is done in two steps, accesses to different ports under EH may race. This primarily is caused by incorrect host locking in EH context and should be fixed by defining locking requirements for each EH operation which can be used during EH and enforcing them but for now work around the problem by adding a dedicated SIDPR lock and grabbing it for each SIDPR access. Signed-off-by: Tejun Heo Reported-by: Mark Knecht Reported-by: Paul Check Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/ata_piix.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 7409f98d2ae6..3971bc0a4838 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -158,6 +158,7 @@ struct piix_map_db { struct piix_host_priv { const int *map; u32 saved_iocfg; + spinlock_t sidpr_lock; /* FIXME: remove once locking in EH is fixed */ void __iomem *sidpr; }; @@ -951,12 +952,15 @@ static int piix_sidpr_scr_read(struct ata_link *link, unsigned int reg, u32 *val) { struct piix_host_priv *hpriv = link->ap->host->private_data; + unsigned long flags; if (reg >= ARRAY_SIZE(piix_sidx_map)) return -EINVAL; + spin_lock_irqsave(&hpriv->sidpr_lock, flags); piix_sidpr_sel(link, reg); *val = ioread32(hpriv->sidpr + PIIX_SIDPR_DATA); + spin_unlock_irqrestore(&hpriv->sidpr_lock, flags); return 0; } @@ -964,12 +968,15 @@ static int piix_sidpr_scr_write(struct ata_link *link, unsigned int reg, u32 val) { struct piix_host_priv *hpriv = link->ap->host->private_data; + unsigned long flags; if (reg >= ARRAY_SIZE(piix_sidx_map)) return -EINVAL; + spin_lock_irqsave(&hpriv->sidpr_lock, flags); piix_sidpr_sel(link, reg); iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA); + spin_unlock_irqrestore(&hpriv->sidpr_lock, flags); return 0; } @@ -1566,6 +1573,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev, hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); if (!hpriv) return -ENOMEM; + spin_lock_init(&hpriv->sidpr_lock); /* Save IOCFG, this will be used for cable detection, quirk * detection and restoration on detach. This is necessary -- cgit v1.2.3 From eca5c118414e728029e764b5ace9b25ced55159d Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 2 Aug 2010 17:17:18 -0500 Subject: perf, powerpc: fsl_emb: Restore setting perf_sample_data.period commit 69e77a8b0426ded5d924eea7dbe4eca51e09f530 upstream. Commit 6b95ed345b9faa4ab3598a82991968f2e9f851bb changed from a struct initializer to perf_sample_data_init(), but the setting of the .period member was left out. Signed-off-by: Scott Wood Signed-off-by: Paul Mackerras Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/perf_event_fsl_emb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/kernel/perf_event_fsl_emb.c b/arch/powerpc/kernel/perf_event_fsl_emb.c index babcceecd2ea..4339d20227b8 100644 --- a/arch/powerpc/kernel/perf_event_fsl_emb.c +++ b/arch/powerpc/kernel/perf_event_fsl_emb.c @@ -569,6 +569,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val, struct perf_sample_data data; perf_sample_data_init(&data, 0); + data.period = event->hw.last_period; if (perf_event_overflow(event, nmi, &data, regs)) { /* -- cgit v1.2.3 From afaac2588bac3673e5e1c6b73fc054c931535175 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 2 Aug 2010 20:47:48 +0000 Subject: powerpc: fix build with make 3.82 commit e32e78c5ee8aadef020fbaecbe6fb741ed9029fd upstream. Thomas Backlund reported that the powerpc build broke with make 3.82. It failed with the following message: arch/powerpc/Makefile:183: *** mixed implicit and normal rules. Stop. The fix is to avoid mixing non-wildcard and wildcard targets. Reported-by: Thomas Backlund Tested-by: Thomas Backlund Cc: Michal Marek Signed-off-by: Sam Ravnborg Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/Makefile | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 77cfe7a29e25..5d2f17dcb728 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -163,9 +163,11 @@ drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ # Default to zImage, override when needed all: zImage -BOOT_TARGETS = zImage zImage.initrd uImage zImage% dtbImage% treeImage.% cuImage.% simpleImage.% +# With make 3.82 we cannot mix normal and wildcard targets +BOOT_TARGETS1 := zImage zImage.initrd uImaged +BOOT_TARGETS2 := zImage% dtbImage% treeImage.% cuImage.% simpleImage.% -PHONY += $(BOOT_TARGETS) +PHONY += $(BOOT_TARGETS1) $(BOOT_TARGETS2) boot := arch/$(ARCH)/boot @@ -180,10 +182,16 @@ relocs_check: arch/powerpc/relocs_check.pl vmlinux zImage: relocs_check endif -$(BOOT_TARGETS): vmlinux +$(BOOT_TARGETS1): vmlinux + $(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@) +$(BOOT_TARGETS2): vmlinux + $(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@) + + +bootwrapper_install: $(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@) -bootwrapper_install %.dtb: +%.dtb: $(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@) define archhelp -- cgit v1.2.3 From 97537a758d5d29534ec0b280403c182fe5155ee5 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Sun, 13 Jun 2010 23:56:54 +0200 Subject: x86, kmmio/mmiotrace: Fix double free of kmmio_fault_pages commit 8b8f79b927b6b302bb65fb8c56e7a19be5fbdbef upstream. After every iounmap mmiotrace has to free kmmio_fault_pages, but it can't do it directly, so it defers freeing by RCU. It usually works, but when mmiotraced code calls ioremap-iounmap multiple times without sleeping between (so RCU won't kick in and start freeing) it can be given the same virtual address, so at every iounmap mmiotrace will schedule the same pages for release. Obviously it will explode on second free. Fix it by marking kmmio_fault_pages which are scheduled for release and not adding them second time. Signed-off-by: Marcin Slusarz Tested-by: Marcin Kocielnicki Tested-by: Shinpei KATO Acked-by: Pekka Paalanen Cc: Stuart Bennett Cc: Marcin Kocielnicki Cc: nouveau@lists.freedesktop.org LKML-Reference: <20100613215654.GA3829@joi.lan> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/kmmio.c | 16 +++++++++++++--- arch/x86/mm/testmmiotrace.c | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c index 5d0e67fff1a6..e5d5e2ce9f77 100644 --- a/arch/x86/mm/kmmio.c +++ b/arch/x86/mm/kmmio.c @@ -45,6 +45,8 @@ struct kmmio_fault_page { * Protected by kmmio_lock, when linked into kmmio_page_table. */ int count; + + bool scheduled_for_release; }; struct kmmio_delayed_release { @@ -398,8 +400,11 @@ static void release_kmmio_fault_page(unsigned long page, BUG_ON(f->count < 0); if (!f->count) { disarm_kmmio_fault_page(f); - f->release_next = *release_list; - *release_list = f; + if (!f->scheduled_for_release) { + f->release_next = *release_list; + *release_list = f; + f->scheduled_for_release = true; + } } } @@ -471,8 +476,10 @@ static void remove_kmmio_fault_pages(struct rcu_head *head) prevp = &f->release_next; } else { *prevp = f->release_next; + f->release_next = NULL; + f->scheduled_for_release = false; } - f = f->release_next; + f = *prevp; } spin_unlock_irqrestore(&kmmio_lock, flags); @@ -510,6 +517,9 @@ void unregister_kmmio_probe(struct kmmio_probe *p) kmmio_count--; spin_unlock_irqrestore(&kmmio_lock, flags); + if (!release_list) + return; + drelease = kmalloc(sizeof(*drelease), GFP_ATOMIC); if (!drelease) { pr_crit("leaking kmmio_fault_page objects.\n"); diff --git a/arch/x86/mm/testmmiotrace.c b/arch/x86/mm/testmmiotrace.c index 8565d944f7cf..38868adf07ea 100644 --- a/arch/x86/mm/testmmiotrace.c +++ b/arch/x86/mm/testmmiotrace.c @@ -90,6 +90,27 @@ static void do_test(unsigned long size) iounmap(p); } +/* + * Tests how mmiotrace behaves in face of multiple ioremap / iounmaps in + * a short time. We had a bug in deferred freeing procedure which tried + * to free this region multiple times (ioremap can reuse the same address + * for many mappings). + */ +static void do_test_bulk_ioremapping(void) +{ + void __iomem *p; + int i; + + for (i = 0; i < 10; ++i) { + p = ioremap_nocache(mmio_address, PAGE_SIZE); + if (p) + iounmap(p); + } + + /* Force freeing. If it will crash we will know why. */ + synchronize_rcu(); +} + static int __init init(void) { unsigned long size = (read_far) ? (8 << 20) : (16 << 10); @@ -104,6 +125,7 @@ static int __init init(void) "and writing 16 kB of rubbish in there.\n", size >> 10, mmio_address); do_test(size); + do_test_bulk_ioremapping(); pr_info("All done.\n"); return 0; } -- cgit v1.2.3 From 4fbb306c756c548a75d480141e327111e4d94d20 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 23 Jul 2010 12:53:27 -0600 Subject: x86/PCI: use host bridge _CRS info on ASRock ALiveSATA2-GLAN commit 2491762cfb475dbdfa3db11ebea6de49f58b7fac upstream. This DMI quirk turns on "pci=use_crs" for the ALiveSATA2-GLAN because amd_bus.c doesn't handle this system correctly. The system has a single HyperTransport I/O chain, but has two PCI host bridges to buses 00 and 80. amd_bus.c learns the MMIO range associated with buses 00-ff and that this range is routed to the HT chain hosted at node 0, link 0: bus: [00, ff] on node 0 link 0 bus: 00 index 1 [mem 0x80000000-0xfcffffffff] This includes the address space for both bus 00 and bus 80, and amd_bus.c assumes it's all routed to bus 00. We find device 80:01.0, which BIOS left in the middle of that space, but we don't find a bridge from bus 00 to bus 80, so we conclude that 80:01.0 is unreachable from bus 00, and we move it from the original, working, address to something outside the bus 00 aperture, which does not work: pci 0000:80:01.0: reg 10: [mem 0xfebfc000-0xfebfffff 64bit] pci 0000:80:01.0: BAR 0: assigned [mem 0xfd00000000-0xfd00003fff 64bit] The BIOS told us everything we need to know to handle this correctly, so we're better off if we just pay attention, which lets us leave the 80:01.0 device at the original, working, address: ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-7f]) pci_root PNP0A03:00: host bridge window [mem 0x80000000-0xff37ffff] ACPI: PCI Root Bridge [PCI1] (domain 0000 [bus 80-ff]) pci_root PNP0A08:00: host bridge window [mem 0xfebfc000-0xfebfffff] This was a regression between 2.6.33 and 2.6.34. In 2.6.33, amd_bus.c was used only when we found multiple HT chains. 3e3da00c01d050, which enabled amd_bus.c even on systems with a single HT chain, caused this failure. This quirk was written by Graham. If we ever enable "pci=use_crs" for machines from 2006 or earlir, this quirk should be removed. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=16007 Reported-by: Graham Ramsey Signed-off-by: Bjorn Helgaas Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman --- arch/x86/pci/acpi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 2ec04c424a62..15466c096ba5 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -34,6 +34,15 @@ static const struct dmi_system_id pci_use_crs_table[] __initconst = { DMI_MATCH(DMI_PRODUCT_NAME, "x3800"), }, }, + /* https://bugzilla.kernel.org/show_bug.cgi?id=16007 */ + /* 2006 AMD HT/VIA system with two host bridges */ + { + .callback = set_use_crs, + .ident = "ASRock ALiveSATA2-GLAN", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "ALiveSATA2-GLAN"), + }, + }, {} }; -- cgit v1.2.3 From 203824bea46cc2d9809833e77dd39780d5bcb20c Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 3 Aug 2010 09:33:45 +0200 Subject: pcmcia: avoid buffer overflow in pcmcia_setup_isa_irq commit 127c03cdbad9bd5af5d7f33bd31a1015a90cb77f upstream. NR_IRQS may be as low as 16, causing a (harmless?) buffer overflow in pcmcia_setup_isa_irq(): static u8 pcmcia_used_irq[NR_IRQS]; ... if ((try < 32) && pcmcia_used_irq[irq]) continue; This is read-only, so if this address would be non-zero, it would just mean we would not attempt an IRQ >= NR_IRQS -- which would fail anyway! And as request_irq() fails for an irq >= NR_IRQS, the setting code path: pcmcia_used_irq[irq]++; is never reached as well. Reported-by: Christoph Fritz Signed-off-by: Dominik Brodowski Signed-off-by: Christoph Fritz Signed-off-by: Greg Kroah-Hartman --- drivers/pcmcia/pcmcia_resource.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index a4cd9adfcbc0..015e27458d81 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -651,7 +651,7 @@ EXPORT_SYMBOL(__pcmcia_request_exclusive_irq); #ifdef CONFIG_PCMCIA_PROBE /* mask of IRQs already reserved by other cards, we should avoid using them */ -static u8 pcmcia_used_irq[NR_IRQS]; +static u8 pcmcia_used_irq[32]; static irqreturn_t test_action(int cpl, void *dev_id) { @@ -674,6 +674,9 @@ static int pcmcia_setup_isa_irq(struct pcmcia_device *p_dev, int type) for (try = 0; try < 64; try++) { irq = try % 32; + if (irq > NR_IRQS) + continue; + /* marked as available by driver, not blocked by userspace? */ if (!((mask >> irq) & 1)) continue; -- cgit v1.2.3 From 568132624386f53e87575195d868db9afb2e9316 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 27 Jul 2010 17:01:49 -0700 Subject: x86: Add memory modify constraints to xchg() and cmpxchg() commit 113fc5a6e8c2288619ff7e8187a6f556b7e0d372 upstream. xchg() and cmpxchg() modify their memory operands, not merely read them. For some versions of gcc the "memory" clobber has apparently dealt with the situation, but not for all. Originally-by: Linus Torvalds Signed-off-by: H. Peter Anvin Cc: Glauber Costa Cc: Avi Kivity Cc: Peter Palfrader Cc: Greg KH Cc: Alan Cox Cc: Zachary Amsden Cc: Marcelo Tosatti LKML-Reference: <4C4F7277.8050306@zytor.com> Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/cmpxchg_32.h | 68 +++++++++++++++++++-------------------- arch/x86/include/asm/cmpxchg_64.h | 40 +++++++++++------------ 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/arch/x86/include/asm/cmpxchg_32.h b/arch/x86/include/asm/cmpxchg_32.h index 8859e12dd3cf..c1cf59d72f09 100644 --- a/arch/x86/include/asm/cmpxchg_32.h +++ b/arch/x86/include/asm/cmpxchg_32.h @@ -27,20 +27,20 @@ struct __xchg_dummy { switch (size) { \ case 1: \ asm volatile("xchgb %b0,%1" \ - : "=q" (__x) \ - : "m" (*__xg(ptr)), "0" (__x) \ + : "=q" (__x), "+m" (*__xg(ptr)) \ + : "0" (__x) \ : "memory"); \ break; \ case 2: \ asm volatile("xchgw %w0,%1" \ - : "=r" (__x) \ - : "m" (*__xg(ptr)), "0" (__x) \ + : "=r" (__x), "+m" (*__xg(ptr)) \ + : "0" (__x) \ : "memory"); \ break; \ case 4: \ asm volatile("xchgl %0,%1" \ - : "=r" (__x) \ - : "m" (*__xg(ptr)), "0" (__x) \ + : "=r" (__x), "+m" (*__xg(ptr)) \ + : "0" (__x) \ : "memory"); \ break; \ default: \ @@ -70,14 +70,14 @@ static inline void __set_64bit(unsigned long long *ptr, unsigned int low, unsigned int high) { asm volatile("\n1:\t" - "movl (%0), %%eax\n\t" - "movl 4(%0), %%edx\n\t" - LOCK_PREFIX "cmpxchg8b (%0)\n\t" + "movl (%1), %%eax\n\t" + "movl 4(%1), %%edx\n\t" + LOCK_PREFIX "cmpxchg8b (%1)\n\t" "jnz 1b" - : /* no outputs */ - : "D"(ptr), - "b"(low), - "c"(high) + : "=m" (*ptr) + : "D" (ptr), + "b" (low), + "c" (high) : "ax", "dx", "memory"); } @@ -121,21 +121,21 @@ extern void __cmpxchg_wrong_size(void); __typeof__(*(ptr)) __new = (new); \ switch (size) { \ case 1: \ - asm volatile(lock "cmpxchgb %b1,%2" \ - : "=a"(__ret) \ - : "q"(__new), "m"(*__xg(ptr)), "0"(__old) \ + asm volatile(lock "cmpxchgb %b2,%1" \ + : "=a" (__ret), "+m" (*__xg(ptr)) \ + : "q" (__new), "0" (__old) \ : "memory"); \ break; \ case 2: \ - asm volatile(lock "cmpxchgw %w1,%2" \ - : "=a"(__ret) \ - : "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ + asm volatile(lock "cmpxchgw %w2,%1" \ + : "=a" (__ret), "+m" (*__xg(ptr)) \ + : "r" (__new), "0" (__old) \ : "memory"); \ break; \ case 4: \ - asm volatile(lock "cmpxchgl %1,%2" \ - : "=a"(__ret) \ - : "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ + asm volatile(lock "cmpxchgl %2,%1" \ + : "=a" (__ret), "+m" (*__xg(ptr)) \ + : "r" (__new), "0" (__old) \ : "memory"); \ break; \ default: \ @@ -180,12 +180,12 @@ static inline unsigned long long __cmpxchg64(volatile void *ptr, unsigned long long new) { unsigned long long prev; - asm volatile(LOCK_PREFIX "cmpxchg8b %3" - : "=A"(prev) - : "b"((unsigned long)new), - "c"((unsigned long)(new >> 32)), - "m"(*__xg(ptr)), - "0"(old) + asm volatile(LOCK_PREFIX "cmpxchg8b %1" + : "=A" (prev), + "+m" (*__xg(ptr)) + : "b" ((unsigned long)new), + "c" ((unsigned long)(new >> 32)), + "0" (old) : "memory"); return prev; } @@ -195,12 +195,12 @@ static inline unsigned long long __cmpxchg64_local(volatile void *ptr, unsigned long long new) { unsigned long long prev; - asm volatile("cmpxchg8b %3" - : "=A"(prev) - : "b"((unsigned long)new), - "c"((unsigned long)(new >> 32)), - "m"(*__xg(ptr)), - "0"(old) + asm volatile("cmpxchg8b %1" + : "=A" (prev), + "+m" (*__xg(ptr)) + : "b" ((unsigned long)new), + "c" ((unsigned long)(new >> 32)), + "0" (old) : "memory"); return prev; } diff --git a/arch/x86/include/asm/cmpxchg_64.h b/arch/x86/include/asm/cmpxchg_64.h index 485ae415faec..b92f147339f3 100644 --- a/arch/x86/include/asm/cmpxchg_64.h +++ b/arch/x86/include/asm/cmpxchg_64.h @@ -26,26 +26,26 @@ extern void __cmpxchg_wrong_size(void); switch (size) { \ case 1: \ asm volatile("xchgb %b0,%1" \ - : "=q" (__x) \ - : "m" (*__xg(ptr)), "0" (__x) \ + : "=q" (__x), "+m" (*__xg(ptr)) \ + : "0" (__x) \ : "memory"); \ break; \ case 2: \ asm volatile("xchgw %w0,%1" \ - : "=r" (__x) \ - : "m" (*__xg(ptr)), "0" (__x) \ + : "=r" (__x), "+m" (*__xg(ptr)) \ + : "0" (__x) \ : "memory"); \ break; \ case 4: \ asm volatile("xchgl %k0,%1" \ - : "=r" (__x) \ - : "m" (*__xg(ptr)), "0" (__x) \ + : "=r" (__x), "+m" (*__xg(ptr)) \ + : "0" (__x) \ : "memory"); \ break; \ case 8: \ asm volatile("xchgq %0,%1" \ - : "=r" (__x) \ - : "m" (*__xg(ptr)), "0" (__x) \ + : "=r" (__x), "+m" (*__xg(ptr)) \ + : "0" (__x) \ : "memory"); \ break; \ default: \ @@ -71,27 +71,27 @@ extern void __cmpxchg_wrong_size(void); __typeof__(*(ptr)) __new = (new); \ switch (size) { \ case 1: \ - asm volatile(lock "cmpxchgb %b1,%2" \ - : "=a"(__ret) \ - : "q"(__new), "m"(*__xg(ptr)), "0"(__old) \ + asm volatile(lock "cmpxchgb %b2,%1" \ + : "=a" (__ret), "+m" (*__xg(ptr)) \ + : "q" (__new), "0" (__old) \ : "memory"); \ break; \ case 2: \ - asm volatile(lock "cmpxchgw %w1,%2" \ - : "=a"(__ret) \ - : "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ + asm volatile(lock "cmpxchgw %w2,%1" \ + : "=a" (__ret), "+m" (*__xg(ptr)) \ + : "r" (__new), "0" (__old) \ : "memory"); \ break; \ case 4: \ - asm volatile(lock "cmpxchgl %k1,%2" \ - : "=a"(__ret) \ - : "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ + asm volatile(lock "cmpxchgl %k2,%1" \ + : "=a" (__ret), "+m" (*__xg(ptr)) \ + : "r" (__new), "0" (__old) \ : "memory"); \ break; \ case 8: \ - asm volatile(lock "cmpxchgq %1,%2" \ - : "=a"(__ret) \ - : "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ + asm volatile(lock "cmpxchgq %2,%1" \ + : "=a" (__ret), "+m" (*__xg(ptr)) \ + : "r" (__new), "0" (__old) \ : "memory"); \ break; \ default: \ -- cgit v1.2.3 From 8f0bb9ae4f4a9eff2cb66837848d1a90ddbb6150 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sun, 25 Jul 2010 16:14:53 -0500 Subject: staging: rt2870: Add USB ID for Belkin F6D4050 v2 commit 5d92fe3387d086fc2f10426fbdb6b86d6cce5a47 upstream. Device missing from current tables. Signed-off-by: Larry Finger Tested-by: Rod Huffaker Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rt2860/usb_main_dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c index 674769d2b59b..c48e85d36f4d 100644 --- a/drivers/staging/rt2860/usb_main_dev.c +++ b/drivers/staging/rt2860/usb_main_dev.c @@ -64,6 +64,7 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x14B2, 0x3C07)}, /* AL */ {USB_DEVICE(0x050D, 0x8053)}, /* Belkin */ {USB_DEVICE(0x050D, 0x825B)}, /* Belkin */ + {USB_DEVICE(0x050D, 0x935B)}, /* Belkin F6D4050 v2 */ {USB_DEVICE(0x14B2, 0x3C23)}, /* Airlink */ {USB_DEVICE(0x14B2, 0x3C27)}, /* Airlink */ {USB_DEVICE(0x07AA, 0x002F)}, /* Corega */ -- cgit v1.2.3 From f224c68398b3cc26d6317688950ab767020fd0e7 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 27 Jul 2010 12:21:19 -0700 Subject: Staging: line6: needs to select SND_PCM commit e928c077e5cdcd72ee762125b37232aec1ff49f3 upstream. line6 uses snd_pcm*() functions, so it should select SND_PCM. ERROR: "snd_pcm_period_elapsed" [drivers/staging/line6/line6usb.ko] undefined! ERROR: "snd_pcm_set_ops" [drivers/staging/line6/line6usb.ko] undefined! ERROR: "snd_pcm_lib_free_pages" [drivers/staging/line6/line6usb.ko] undefined! ERROR: "snd_pcm_lib_ioctl" [drivers/staging/line6/line6usb.ko] undefined! ERROR: "snd_pcm_lib_malloc_pages" [drivers/staging/line6/line6usb.ko] undefined! ERROR: "snd_pcm_hw_constraint_ratdens" [drivers/staging/line6/line6usb.ko] undefined! ERROR: "snd_pcm_format_physical_width" [drivers/staging/line6/line6usb.ko] undefined! ERROR: "snd_pcm_lib_preallocate_pages_for_all" [drivers/staging/line6/line6usb.ko] undefined! ERROR: "snd_pcm_new" [drivers/staging/line6/line6usb.ko] undefined! Signed-off-by: Randy Dunlap Cc: Markus Grabner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/line6/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/line6/Kconfig b/drivers/staging/line6/Kconfig index 7852d4a960c5..bc1ffbed3c8a 100644 --- a/drivers/staging/line6/Kconfig +++ b/drivers/staging/line6/Kconfig @@ -2,6 +2,7 @@ config LINE6_USB tristate "Line6 USB support" depends on USB && SND select SND_RAWMIDI + select SND_PCM help This is a driver for the guitar amp, cab, and effects modeller PODxt Pro by Line6 (and similar devices), supporting the -- cgit v1.2.3 From f4a92a3597f7e22ea7dee67970e7b10bd1241321 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Wed, 7 Jul 2010 04:52:16 +0200 Subject: Staging: panel: Prevent double-calling of parport_release - fix oops. commit 060132ae42cce3f9d2fd34d9a17b98362b44b9f9 upstream. This patch prevents the code from calling parport_release and parport_unregister_device twice with the same arguments - and thus fixes an oops. Rationale: After the first call the parport is already released and the handle isn't valid anymore and calling parport_release and parport_unregister_device twice isn't a good idea. Signed-off-by: Peter Huewe Acked-by: Willy Tarreau Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 9ca0e9e2a961..6474c3a77e6c 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -2179,6 +2179,7 @@ int panel_init(void) if (pprt) { parport_release(pprt); parport_unregister_device(pprt); + pprt = NULL; } parport_unregister_driver(&panel_driver); printk(KERN_ERR "Panel driver version " PANEL_VERSION @@ -2228,6 +2229,7 @@ static void __exit panel_cleanup_module(void) /* TODO: free all input signals */ parport_release(pprt); parport_unregister_device(pprt); + pprt = NULL; } parport_unregister_driver(&panel_driver); } -- cgit v1.2.3 From 570d6f5c731d4e1db796054a891701da6ff06c4a Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Fri, 23 Jul 2010 21:24:42 +0000 Subject: staging: hv: Fix Kconfig dependency of hv_blkvsc commit 54d2379c20d814ced657cbc2c4ead8d1f8389fa2 upstream. LBDAF is not available nor necessary on 64BIT kernel. This patch fixed the dependency for hv_blkvsc module on 64BIT kernel. Thanks vrataj2 [vrataj2@comcast.net] for reporting this problem. Reported-by: vrataj2 Signed-off-by: Haiyang Zhang Signed-off-by: Hank Janssen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/hv/Kconfig b/drivers/staging/hv/Kconfig index 97480f5c6599..7455c804962a 100644 --- a/drivers/staging/hv/Kconfig +++ b/drivers/staging/hv/Kconfig @@ -17,7 +17,7 @@ config HYPERV_STORAGE config HYPERV_BLOCK tristate "Microsoft Hyper-V virtual block driver" - depends on BLOCK && SCSI && LBDAF + depends on BLOCK && SCSI && (LBDAF || 64BIT) default HYPERV help Select this option to enable the Hyper-V virtual block driver. -- cgit v1.2.3 From 855b9e05fb274406d11f5920b2b80e6f1eeefb49 Mon Sep 17 00:00:00 2001 From: Lytochkin Boris Date: Mon, 26 Jul 2010 10:02:26 +0400 Subject: serial: add support for OX16PCI958 card commit e847003f00d5eca3e3b3a6a1199f82b51293faf6 upstream. Signed-off-by: Lytochkin Boris Tested-by: Lytochkin Boris Signed-off-by: Alexander Beregalov Signed-off-by: Greg Kroah-Hartman --- drivers/serial/8250_pci.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 746a44621d91..53be4d35a0aa 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -994,6 +994,7 @@ static int skip_tx_en_setup(struct serial_private *priv, #define PCI_DEVICE_ID_TITAN_800E 0xA014 #define PCI_DEVICE_ID_TITAN_200EI 0xA016 #define PCI_DEVICE_ID_TITAN_200EISI 0xA017 +#define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 @@ -1542,6 +1543,8 @@ enum pci_board_num_t { pbn_b2_4_921600, pbn_b2_8_921600, + pbn_b2_8_1152000, + pbn_b2_bt_1_115200, pbn_b2_bt_2_115200, pbn_b2_bt_4_115200, @@ -1960,6 +1963,13 @@ static struct pciserial_board pci_boards[] __devinitdata = { .uart_offset = 8, }, + [pbn_b2_8_1152000] = { + .flags = FL_BASE2, + .num_ports = 8, + .base_baud = 1152000, + .uart_offset = 8, + }, + [pbn_b2_bt_1_115200] = { .flags = FL_BASE2|FL_BASE_BARS, .num_ports = 1, @@ -2875,6 +2885,9 @@ static struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_2_921600 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI958, + PCI_ANY_ID , PCI_ANY_ID, 0, 0, + pbn_b2_8_1152000 }, /* * Oxford Semiconductor Inc. Tornado PCI express device range. -- cgit v1.2.3 From 692f3d4ad794405d87b26ff008eb433b55409290 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 23 Jul 2010 22:19:55 +0200 Subject: PCI: Do not run NVidia quirks related to MSI with MSI disabled commit 3d2a531804d16cd8df6dbbb0429c6f143e756049 upstream. There is no reason to run NVidia-specific quirks related to HT MSI mappings with MSI disabled via pci=nomsi, so make __nv_msi_ht_cap_quirk() return immediately in that case. This allows at least one machine to boot 100% of the time with pci=nomsi (it still doesn't boot reliably without that). Addresses https://bugzilla.kernel.org/show_bug.cgi?id=16443 . Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 477345d41641..9286ed3c6b30 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2390,6 +2390,9 @@ static void __devinit __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all) int pos; int found; + if (!pci_msi_enabled()) + return; + /* check if there is HT MSI cap or enabled on this device */ found = ht_check_msi_mapping(dev); -- cgit v1.2.3 From ecfd2b1639f21f6843551d553ba95991f23ca19a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 23 May 2010 10:22:55 +0200 Subject: PCI: disable MSI on VIA K8M800 commit 549e15611b4ac1de51ef0e0a79c2704f50a638a2 upstream. MSI delivery from on-board ahci controller doesn't work on K8M800. At this point, it's unclear whether the culprit is with the ahci controller or the host bridge. Given the track record and considering the rather minimal impact of MSI, disabling it seems reasonable. Signed-off-by: Tejun Heo Reported-by: Rainer Hurtado Navarro Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 9286ed3c6b30..e28524ec7cee 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2115,6 +2115,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disabl DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3336, quirk_disable_all_msi); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3364, quirk_disable_all_msi); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8380_0, quirk_disable_all_msi); /* Disable MSI on chipsets that are known to not support it */ static void __devinit quirk_disable_msi(struct pci_dev *dev) -- cgit v1.2.3 From 9e90e744b474264c6a7526b150fa3112a2b1765f Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 7 Aug 2010 23:02:59 -0700 Subject: solos-pci: Fix race condition in tasklet RX handling commit 1f6ea6e511e5ec730d8e88651da1b7b6e8fd1333 upstream. We were seeing faults in the solos-pci receive tasklet when packets arrived for a VCC which was currently being closed: [18842.727906] EIP: [] br2684_push+0x19/0x234 [br2684] SS:ESP 0068:dfb89d14 [18845.090712] [] ? do_page_fault+0x0/0x2e1 [18845.120042] [] ? br2684_push+0x19/0x234 [br2684] [18845.153530] [] solos_bh+0x28b/0x7c8 [solos_pci] [18845.186488] [] ? solos_irq+0x2d/0x51 [solos_pci] [18845.219960] [] ? handle_irq+0x3b/0x48 [18845.247732] [] ? irq_exit+0x34/0x57 [18845.274437] [] tasklet_action+0x42/0x69 [18845.303247] [] __do_softirq+0x8e/0x129 [18845.331540] [] do_softirq+0x25/0x2a [18845.358274] [] _local_bh_enable_ip+0x5e/0x6a [18845.389677] [] local_bh_enable+0xb/0xe [18845.417944] [] ppp_unregister_channel+0x32/0xbb [ppp_generic] [18845.458193] [] pppox_unbind_sock+0x18/0x1f [pppox] This patch uses an RCU-inspired approach to fix it. In the RX tasklet's find_vcc() function we first refuse to use a VCC which already has the ATM_VF_READY bit cleared. And in the VCC close function, we synchronise with the tasklet to ensure that it can't still be using the VCC before we continue and allow the VCC to be destroyed. Signed-off-by: David Woodhouse Tested-by: Nathan Williams Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/atm/solos-pci.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index ded76c4c9f4f..36134221abd4 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -781,7 +781,8 @@ static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci) sk_for_each(s, node, head) { vcc = atm_sk(s); if (vcc->dev == dev && vcc->vci == vci && - vcc->vpi == vpi && vcc->qos.rxtp.traffic_class != ATM_NONE) + vcc->vpi == vpi && vcc->qos.rxtp.traffic_class != ATM_NONE && + test_bit(ATM_VF_READY, &vcc->flags)) goto out; } vcc = NULL; @@ -907,6 +908,10 @@ static void pclose(struct atm_vcc *vcc) clear_bit(ATM_VF_ADDR, &vcc->flags); clear_bit(ATM_VF_READY, &vcc->flags); + /* Hold up vcc_destroy_socket() (our caller) until solos_bh() in the + tasklet has finished processing any incoming packets (and, more to + the point, using the vcc pointer). */ + tasklet_unlock_wait(&card->tlet); return; } -- cgit v1.2.3 From f38a529fddcb2dd5eb11d7821b4015a7c8dd3b50 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Fri, 30 Jul 2010 11:46:42 -0700 Subject: x86, mtrr: Use stop machine context to rendezvous all the cpu's commit 68f202e4e87cfab4439568bf397fcc5c7cf8d729 upstream. Use the stop machine context rather than IPI's to rendezvous all the cpus for MTRR initialization that happens during cpu bringup or for MTRR modifications during runtime. This avoids deadlock scenario (reported by Prarit) like: cpu A holds a read_lock (tasklist_lock for example) with irqs enabled cpu B waits for the same lock with irqs disabled using write_lock_irq cpu C doing set_mtrr() (during AP bringup for example), which will try to rendezvous all the cpus using IPI's This will result in C and A come to the rendezvous point and waiting for B. B is stuck forever waiting for the lock and thus not reaching the rendezvous point. Using stop cpu (run in the process context of per cpu based keventd) to do this rendezvous, avoids this deadlock scenario. Also make sure all the cpu's are in the rendezvous handler before we proceed with the local_irq_save() on each cpu. This lock step disabling irqs on all the cpus will avoid other deadlock scenarios (for example involving with the blocking smp_call_function's etc). [ This problem is very old. Marking -stable only for 2.6.35 as the stop_one_cpu_nowait() API is present only in 2.6.35. Any older kernel interested in this fix need to do some more work in backporting this patch. ] Reported-by: Prarit Bhargava Signed-off-by: Suresh Siddha LKML-Reference: <1280515602.2682.10.camel@sbsiddha-MOBL3.sc.intel.com> Acked-by: Prarit Bhargava Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mtrr/main.c | 56 +++++++++++++++++++++++++++++++---------- arch/x86/kernel/smpboot.c | 7 ++++++ 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 79556bd9b602..01c0f3ee6cc3 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -35,6 +35,7 @@ #include /* FIXME: kvm_para.h needs this */ +#include #include #include #include @@ -143,22 +144,28 @@ struct set_mtrr_data { mtrr_type smp_type; }; +static DEFINE_PER_CPU(struct cpu_stop_work, mtrr_work); + /** - * ipi_handler - Synchronisation handler. Executed by "other" CPUs. + * mtrr_work_handler - Synchronisation handler. Executed by "other" CPUs. * @info: pointer to mtrr configuration data * * Returns nothing. */ -static void ipi_handler(void *info) +static int mtrr_work_handler(void *info) { #ifdef CONFIG_SMP struct set_mtrr_data *data = info; unsigned long flags; + atomic_dec(&data->count); + while (!atomic_read(&data->gate)) + cpu_relax(); + local_irq_save(flags); atomic_dec(&data->count); - while (!atomic_read(&data->gate)) + while (atomic_read(&data->gate)) cpu_relax(); /* The master has cleared me to execute */ @@ -173,12 +180,13 @@ static void ipi_handler(void *info) } atomic_dec(&data->count); - while (atomic_read(&data->gate)) + while (!atomic_read(&data->gate)) cpu_relax(); atomic_dec(&data->count); local_irq_restore(flags); #endif + return 0; } static inline int types_compatible(mtrr_type type1, mtrr_type type2) @@ -198,7 +206,7 @@ static inline int types_compatible(mtrr_type type1, mtrr_type type2) * * This is kinda tricky, but fortunately, Intel spelled it out for us cleanly: * - * 1. Send IPI to do the following: + * 1. Queue work to do the following on all processors: * 2. Disable Interrupts * 3. Wait for all procs to do so * 4. Enter no-fill cache mode @@ -215,14 +223,17 @@ static inline int types_compatible(mtrr_type type1, mtrr_type type2) * 15. Enable interrupts. * * What does that mean for us? Well, first we set data.count to the number - * of CPUs. As each CPU disables interrupts, it'll decrement it once. We wait - * until it hits 0 and proceed. We set the data.gate flag and reset data.count. - * Meanwhile, they are waiting for that flag to be set. Once it's set, each + * of CPUs. As each CPU announces that it started the rendezvous handler by + * decrementing the count, We reset data.count and set the data.gate flag + * allowing all the cpu's to proceed with the work. As each cpu disables + * interrupts, it'll decrement data.count once. We wait until it hits 0 and + * proceed. We clear the data.gate flag and reset data.count. Meanwhile, they + * are waiting for that flag to be cleared. Once it's cleared, each * CPU goes through the transition of updating MTRRs. * The CPU vendors may each do it differently, * so we call mtrr_if->set() callback and let them take care of it. * When they're done, they again decrement data->count and wait for data.gate - * to be reset. + * to be set. * When we finish, we wait for data.count to hit 0 and toggle the data.gate flag * Everyone then enables interrupts and we all continue on. * @@ -234,6 +245,9 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ { struct set_mtrr_data data; unsigned long flags; + int cpu; + + preempt_disable(); data.smp_reg = reg; data.smp_base = base; @@ -246,10 +260,15 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ atomic_set(&data.gate, 0); /* Start the ball rolling on other CPUs */ - if (smp_call_function(ipi_handler, &data, 0) != 0) - panic("mtrr: timed out waiting for other CPUs\n"); + for_each_online_cpu(cpu) { + struct cpu_stop_work *work = &per_cpu(mtrr_work, cpu); + + if (cpu == smp_processor_id()) + continue; + + stop_one_cpu_nowait(cpu, mtrr_work_handler, &data, work); + } - local_irq_save(flags); while (atomic_read(&data.count)) cpu_relax(); @@ -259,6 +278,16 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ smp_wmb(); atomic_set(&data.gate, 1); + local_irq_save(flags); + + while (atomic_read(&data.count)) + cpu_relax(); + + /* Ok, reset count and toggle gate */ + atomic_set(&data.count, num_booting_cpus() - 1); + smp_wmb(); + atomic_set(&data.gate, 0); + /* Do our MTRR business */ /* @@ -279,7 +308,7 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ atomic_set(&data.count, num_booting_cpus() - 1); smp_wmb(); - atomic_set(&data.gate, 0); + atomic_set(&data.gate, 1); /* * Wait here for everyone to have seen the gate change @@ -289,6 +318,7 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ cpu_relax(); local_irq_restore(flags); + preempt_enable(); } /** diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index c4f33b2e77d6..11015fd1abbc 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -816,6 +816,13 @@ do_rest: if (cpumask_test_cpu(cpu, cpu_callin_mask)) break; /* It has booted */ udelay(100); + /* + * Allow other tasks to run while we wait for the + * AP to come online. This also gives a chance + * for the MTRR work(triggered by the AP coming online) + * to be completed in the stop machine context. + */ + schedule(); } if (cpumask_test_cpu(cpu, cpu_callin_mask)) -- cgit v1.2.3 From a88549a429aefa85807f92d19056824497ddd8cd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 3 Aug 2010 17:20:35 +0200 Subject: ALSA: hda - Add PC-beep whitelist for an Intel board commit e096c8e6d5ed965f346d94befbbec2275dde3621 upstream. An Intel board needs a white-list entry to enable PC-beep. Otherwise the driver misdetects (due to bogus BIOS info) and ignores the PC-beep on 2.6.35. Reported-and-tested-by: Leandro Lucarella Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 596ea2f12cf6..aa7cc519e7b8 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5183,6 +5183,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, static struct snd_pci_quirk beep_white_list[] = { SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), + SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1), {} }; -- cgit v1.2.3 From 8642acfa5eb90d591f72ef762ac7e188b6e30e96 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 29 Jul 2010 11:09:47 +0200 Subject: Char: nozomi, fix tty->count counting commit ee78bb95b7bea08b7774a02073ea2bb45611a9e1 upstream. Currently ntty_install omits to increment tty count and we get the following warnings: Warning: dev (noz2) tty->count(0) != #fd's(1) in tty_open So to fix that, add one tty->count++ there. Signed-off-by: Jiri Slaby Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/nozomi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index a6638003f530..21ae1b158b3b 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -1611,6 +1611,7 @@ static int ntty_install(struct tty_driver *driver, struct tty_struct *tty) ret = tty_init_termios(tty); if (ret == 0) { tty_driver_kref_get(driver); + tty->count++; driver->ttys[tty->index] = tty; } return ret; -- cgit v1.2.3 From 69348a6d2e12b2212ce7516f607d05a94ca9abd4 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 29 Jul 2010 11:46:32 +0200 Subject: Char: nozomi, set tty->driver_data appropriately commit bf9c1fca9ae9a79ed209e7ab2c10b3862f3f6f72 upstream. Sorry, one more fix, this one depends on the other, so this is rather 2/2. -- tty->driver_data is used all over the code, but never set. This results in oopses like: BUG: unable to handle kernel NULL pointer dereference at 0000000000000130 IP: [] mutex_lock+0x10/0x40 ... Pid: 2157, comm: modem-manager Not tainted 2.6.34.1-0.1-desktop #1 2768DR7/2768DR7 RIP: 0010:[] [] mutex_lock+0x10/0x40 RSP: 0018:ffff88007b16fa50 EFLAGS: 00010286 RAX: 0000000000000000 RBX: 0000000000000130 RCX: 0000000000000003 RDX: 0000000000000003 RSI: 0000000000000286 RDI: 0000000000000130 RBP: 0000000000001000 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000130 R13: 0000000000000001 R14: 0000000000000000 R15: ffff88007b16feb4 ... Call Trace: [] ntty_write_room+0x4d/0x90 [nozomi] ... Set tty->driver_data to the computed port in .install to not recompute it in every place where needed. Switch .open to use driver_data too. Signed-off-by: Jiri Slaby Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/nozomi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 21ae1b158b3b..18af923093c3 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -1612,6 +1612,7 @@ static int ntty_install(struct tty_driver *driver, struct tty_struct *tty) if (ret == 0) { tty_driver_kref_get(driver); tty->count++; + tty->driver_data = port; driver->ttys[tty->index] = tty; } return ret; @@ -1640,7 +1641,7 @@ static int ntty_activate(struct tty_port *tport, struct tty_struct *tty) static int ntty_open(struct tty_struct *tty, struct file *filp) { - struct port *port = get_port_by_tty(tty); + struct port *port = tty->driver_data; return tty_port_open(&port->port, tty, filp); } -- cgit v1.2.3 From c5e1a7d54dda4427f8d697b8a49ccadf6496b67f Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Mon, 9 Aug 2010 17:20:09 -0700 Subject: mm: fix corruption of hibernation caused by reusing swap during image saving commit 966cca029f739716fbcc8068b8c6dfe381f86fc3 upstream. Since 2.6.31, swap_map[]'s refcounting was changed to show that a used swap entry is just for swap-cache, can be reused. Then, while scanning free entry in swap_map[], a swap entry may be able to be reclaimed and reused. It was caused by commit c9e444103b5e7a5 ("mm: reuse unused swap entry if necessary"). But this caused deta corruption at resume. The scenario is - Assume a clean-swap cache, but mapped. - at hibernation_snapshot[], clean-swap-cache is saved as clean-swap-cache and swap_map[] is marked as SWAP_HAS_CACHE. - then, save_image() is called. And reuse SWAP_HAS_CACHE entry to save image, and break the contents. After resume: - the memory reclaim runs and finds clean-not-referenced-swap-cache and discards it because it's marked as clean. But here, the contents on disk and swap-cache is inconsistent. Hance memory is corrupted. This patch avoids the bug by not reclaiming swap-entry during hibernation. This is a quick fix for backporting. Signed-off-by: KAMEZAWA Hiroyuki Cc: Rafael J. Wysocki Reported-by: Ondreg Zary Tested-by: Ondreg Zary Tested-by: Andrea Gelmini Acked-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/swapfile.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/swapfile.c b/mm/swapfile.c index 03aa2d55f1a2..f08d165871b3 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -318,8 +318,10 @@ checks: if (offset > si->highest_bit) scan_base = offset = si->lowest_bit; - /* reuse swap entry of cache-only swap if not busy. */ - if (vm_swap_full() && si->swap_map[offset] == SWAP_HAS_CACHE) { + /* reuse swap entry of cache-only swap if not hibernation. */ + if (vm_swap_full() + && usage == SWAP_HAS_CACHE + && si->swap_map[offset] == SWAP_HAS_CACHE) { int swap_was_freed; spin_unlock(&swap_lock); swap_was_freed = __try_to_reclaim_swap(si, offset); -- cgit v1.2.3 From ef5cd7c116b865dee3955c6e2c9ca05dd6268ade Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 9 Aug 2010 17:18:23 -0700 Subject: drivers/video/w100fb.c: ignore void return value / fix build failure commit fa260c00c1aa5c657793a7221e40d2400df5afd8 upstream. Fix a build failure "error: void value not ignored as it ought to be" by removing an assignment of a void return value. The functionality of the code is not changed. Signed-off-by: Peter Huewe Acked-by: Henrik Kretzschmar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/video/w100fb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index e66b8b19ce5d..d8b12c32e3ef 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c @@ -858,9 +858,9 @@ unsigned long w100fb_gpio_read(int port) void w100fb_gpio_write(int port, unsigned long value) { if (port==W100_GPIO_PORT_A) - value = writel(value, remapped_regs + mmGPIO_DATA); + writel(value, remapped_regs + mmGPIO_DATA); else - value = writel(value, remapped_regs + mmGPIO_DATA2); + writel(value, remapped_regs + mmGPIO_DATA2); } EXPORT_SYMBOL(w100fb_gpio_read); EXPORT_SYMBOL(w100fb_gpio_write); -- cgit v1.2.3 From 563fd08347da83e595b07c8515b8b2f64033bcf6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 6 Aug 2010 16:00:48 +0200 Subject: iwlwifi: fix TX tracer commit e95b743536937a72e1560c85696b425c5d1a1c18 upstream. The TX tracing code copies with the wrong length, which will typically copy too little data. Fix this by using the correct length variable. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-devtrace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index ae7319bb3a99..4cf864c664ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -193,7 +193,7 @@ TRACE_EVENT(iwlwifi_dev_tx, __entry->framelen = buf0_len + buf1_len; memcpy(__get_dynamic_array(tfd), tfd, tfdlen); memcpy(__get_dynamic_array(buf0), buf0, buf0_len); - memcpy(__get_dynamic_array(buf1), buf1, buf0_len); + memcpy(__get_dynamic_array(buf1), buf1, buf1_len); ), TP_printk("[%p] TX %.2x (%zu bytes)", __entry->priv, -- cgit v1.2.3 From d3c5501ec90af293e011b036e9c5871b300d304e Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 5 Aug 2010 13:46:27 -0400 Subject: rtl8180: avoid potential NULL deref in rtl8180_beacon_work commit 8f1d2d2be73a98c21e68fe2a26f633892d4abdd1 upstream. ieee80211_beacon_get can return NULL... Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtl818x/rtl8180_dev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 515817de2905..15f09e81614e 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -688,6 +688,8 @@ void rtl8180_beacon_work(struct work_struct *work) /* grab a fresh beacon */ skb = ieee80211_beacon_get(dev, vif); + if (!skb) + goto resched; /* * update beacon timestamp w/ TSF value -- cgit v1.2.3 From 3821841da74077e09f22e9245a98a7e79016fbd1 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 9 Aug 2010 17:18:22 -0700 Subject: ipmi: fix ACPI detection with regspacing commit d9e1b6c45059ccfff647a120769ae86da78dfdc4 upstream. After the commit that changed ipmi_si detecting sequence from SMBIOS/ACPI to ACPI/SMBIOS, | commit 754d453185275951d39792865927ec494fa1ebd8 | Author: Matthew Garrett | Date: Wed May 26 14:43:47 2010 -0700 | | ipmi: change device discovery order | | The ipmi spec provides an ordering for si discovery. Change the driver to | match, with the exception of preferring smbios to SPMI as HPs (at least) | contain accurate information in the former but not the latter. ipmi_si can not be initialized. [ 138.799739] calling init_ipmi_devintf+0x0/0x109 @ 1 [ 138.805050] ipmi device interface [ 138.818131] initcall init_ipmi_devintf+0x0/0x109 returned 0 after 12797 usecs [ 138.822998] calling init_ipmi_si+0x0/0xa90 @ 1 [ 138.840276] IPMI System Interface driver. [ 138.846137] ipmi_si: probing via ACPI [ 138.849225] ipmi_si 00:09: [io 0x0ca2] regsize 1 spacing 1 irq 0 [ 138.864438] ipmi_si: Adding ACPI-specified kcs state machine [ 138.870893] ipmi_si: probing via SMBIOS [ 138.880945] ipmi_si: Adding SMBIOS-specified kcs state machineipmi_si: duplicate interface [ 138.896511] ipmi_si: probing via SPMI [ 138.899861] ipmi_si: Adding SPMI-specified kcs state machineipmi_si: duplicate interface [ 138.917095] ipmi_si: Trying ACPI-specified kcs state machine at i/o address 0xca2, slave address 0x0, irq 0 [ 138.928658] ipmi_si: Interface detection failed [ 138.953411] initcall init_ipmi_si+0x0/0xa90 returned 0 after 110847 usecs in smbios has DMI/SMBIOS Handle 0x00C5, DMI type 38, 18 bytes IPMI Device Information Interface Type: KCS (Keyboard Control Style) Specification Version: 2.0 I2C Slave Address: 0x00 NV Storage Device: Not Present Base Address: 0x0000000000000CA2 (I/O) Register Spacing: 32-bit Boundaries in DSDT has Device (BMC) { Name (_HID, EisaId ("IPI0001")) Method (_STA, 0, NotSerialized) { If (LEqual (OSN, Zero)) { Return (Zero) } Return (0x0F) } Name (_STR, Unicode ("IPMI_KCS")) Name (_UID, Zero) Name (_CRS, ResourceTemplate () { IO (Decode16, 0x0CA2, // Range Minimum 0x0CA2, // Range Maximum 0x00, // Alignment 0x01, // Length ) IO (Decode16, 0x0CA6, // Range Minimum 0x0CA6, // Range Maximum 0x00, // Alignment 0x01, // Length ) }) Method (_IFT, 0, NotSerialized) { Return (One) } Method (_SRV, 0, NotSerialized) { Return (0x0200) } } so the reg spacing should be 4 instead of 1. Try to calculate regspacing for this kind of system. Observed on a Sun Fire X4800. Other OSes work and pass certification. Signed-off-by: Yinghai Lu Cc: Bjorn Helgaas Acked-by: Matthew Garrett Cc: Len Brown Cc: Myron Stowe Cc: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/char/ipmi/ipmi_si_intf.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 094bdc355b1f..ff68e7c34ce7 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2176,6 +2176,14 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, info->io.addr_data = res->start; info->io.regspacing = DEFAULT_REGSPACING; + res = pnp_get_resource(dev, + (info->io.addr_type == IPMI_IO_ADDR_SPACE) ? + IORESOURCE_IO : IORESOURCE_MEM, + 1); + if (res) { + if (res->start > info->io.addr_data) + info->io.regspacing = res->start - info->io.addr_data; + } info->io.regsize = DEFAULT_REGSPACING; info->io.regshift = 0; -- cgit v1.2.3 From 8a4ddef0916fea7b0dae2ae5b5fc287029e2208e Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 5 Jul 2010 21:23:52 -0700 Subject: ide-cd: Do not access completed requests in the irq handler commit 110712828365ccafcc61a7f4db44c31ed4cf8793 upstream. ide_cd_error_cmd() can complete an erroneous request with leftover buffers. Signal this with its return value so that the request is not accessed after its completion in the irq handler and we oops. Signed-off-by: Borislav Petkov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/ide/ide-cd.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 64207df8da82..2de76cc08f61 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -506,15 +506,22 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, return (flags & REQ_FAILED) ? -EIO : 0; } -static void ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd) +/* + * returns true if rq has been completed + */ +static bool ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd) { unsigned int nr_bytes = cmd->nbytes - cmd->nleft; if (cmd->tf_flags & IDE_TFLAG_WRITE) nr_bytes -= cmd->last_xfer_len; - if (nr_bytes > 0) + if (nr_bytes > 0) { ide_complete_rq(drive, 0, nr_bytes); + return true; + } + + return false; } static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) @@ -679,7 +686,8 @@ out_end: } if (uptodate == 0 && rq->bio) - ide_cd_error_cmd(drive, cmd); + if (ide_cd_error_cmd(drive, cmd)) + return ide_stopped; /* make sure it's fully ended */ if (blk_fs_request(rq) == 0) { -- cgit v1.2.3 From 3b9f17f709e0b691940bfd9eda45b716932696f6 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 6 Aug 2010 18:01:59 -0700 Subject: md: move revalidate_disk() back outside open_mutex commit 147e0b6a639ac581ca3bf627bedc3f4a6d3eca66 upstream. Commit b821eaa5 "md: remove ->changed and related code" moved revalidate_disk() under open_mutex, and lockdep noticed. [ INFO: possible circular locking dependency detected ] 2.6.32-mdadm-locking #1 ------------------------------------------------------- mdadm/3640 is trying to acquire lock: (&bdev->bd_mutex){+.+.+.}, at: [] revalidate_disk+0x5b/0x90 but task is already holding lock: (&mddev->open_mutex){+.+...}, at: [] do_md_stop+0x4a/0x4d0 [md_mod] which lock already depends on the new lock. It is suitable for 2.6.35.x Reported-by: Przemyslaw Czarnowski Signed-off-by: Dan Williams Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index cb20d0b0555a..9743554694f0 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4711,7 +4711,7 @@ out: */ static int do_md_stop(mddev_t * mddev, int mode, int is_open) { - int err = 0; + int err = 0, revalidate = 0; struct gendisk *disk = mddev->gendisk; mdk_rdev_t *rdev; @@ -4740,7 +4740,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) } set_capacity(disk, 0); - revalidate_disk(disk); + revalidate = 1; if (mddev->ro) mddev->ro = 0; @@ -4748,6 +4748,8 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) err = 0; } mutex_unlock(&mddev->open_mutex); + if (revalidate) + revalidate_disk(disk); if (err) return err; /* -- cgit v1.2.3 From 8fa8b10c9dc5729d3af41babae879b48ab4ee095 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 8 Aug 2010 21:18:03 +1000 Subject: md: fix another deadlock with removing sysfs attributes. commit bb4f1e9d0e2ef93de8e36ca0f5f26625fcd70b7d upstream. Move the deletion of sysfs attributes from reconfig_mutex to open_mutex didn't really help as a process can try to take open_mutex while holding reconfig_mutex, so the same deadlock can happen, just requiring one more process to be involved in the chain. I looks like I cannot easily use locking to wait for the sysfs deletion to complete, so don't. The only things that we cannot do while the deletions are still pending is other things which can change the sysfs namespace: run, takeover, stop. Each of these can fail with -EBUSY. So set a flag while doing a sysfs deletion, and fail run, takeover, stop if that flag is set. This is suitable for 2.6.35.x Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 31 +++++++++++++++++-------------- drivers/md/md.h | 4 ++++ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 9743554694f0..7476d959090f 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -532,13 +532,17 @@ static void mddev_unlock(mddev_t * mddev) * an access to the files will try to take reconfig_mutex * while holding the file unremovable, which leads to * a deadlock. - * So hold open_mutex instead - we are allowed to take - * it while holding reconfig_mutex, and md_run can - * use it to wait for the remove to complete. + * So hold set sysfs_active while the remove in happeing, + * and anything else which might set ->to_remove or my + * otherwise change the sysfs namespace will fail with + * -EBUSY if sysfs_active is still set. + * We set sysfs_active under reconfig_mutex and elsewhere + * test it under the same mutex to ensure its correct value + * is seen. */ struct attribute_group *to_remove = mddev->to_remove; mddev->to_remove = NULL; - mutex_lock(&mddev->open_mutex); + mddev->sysfs_active = 1; mutex_unlock(&mddev->reconfig_mutex); if (to_remove != &md_redundancy_group) @@ -550,7 +554,7 @@ static void mddev_unlock(mddev_t * mddev) sysfs_put(mddev->sysfs_action); mddev->sysfs_action = NULL; } - mutex_unlock(&mddev->open_mutex); + mddev->sysfs_active = 0; } else mutex_unlock(&mddev->reconfig_mutex); @@ -2960,7 +2964,9 @@ level_store(mddev_t *mddev, const char *buf, size_t len) * - new personality will access other array. */ - if (mddev->sync_thread || mddev->reshape_position != MaxSector) + if (mddev->sync_thread || + mddev->reshape_position != MaxSector || + mddev->sysfs_active) return -EBUSY; if (!mddev->pers->quiesce) { @@ -4344,13 +4350,9 @@ static int md_run(mddev_t *mddev) if (mddev->pers) return -EBUSY; - - /* These two calls synchronise us with the - * sysfs_remove_group calls in mddev_unlock, - * so they must have completed. - */ - mutex_lock(&mddev->open_mutex); - mutex_unlock(&mddev->open_mutex); + /* Cannot run until previous stop completes properly */ + if (mddev->sysfs_active) + return -EBUSY; /* * Analyze all RAID superblock(s) @@ -4716,7 +4718,8 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) mdk_rdev_t *rdev; mutex_lock(&mddev->open_mutex); - if (atomic_read(&mddev->openers) > is_open) { + if (atomic_read(&mddev->openers) > is_open || + mddev->sysfs_active) { printk("md: %s still in use.\n",mdname(mddev)); err = -EBUSY; } else if (mddev->pers) { diff --git a/drivers/md/md.h b/drivers/md/md.h index 10597bfec000..9ec208e11fbf 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -125,6 +125,10 @@ struct mddev_s int suspended; atomic_t active_io; int ro; + int sysfs_active; /* set when sysfs deletes + * are happening, so run/ + * takeover/stop are not safe + */ struct gendisk *gendisk; -- cgit v1.2.3 From f986737b930114d41549f405a4efdeb13002db70 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 7 Aug 2010 21:17:00 +1000 Subject: md/raid10: fix deadlock with unaligned read during resync commit 51e9ac77035a3dfcb6fc0a88a0d80b6f99b5edb1 upstream. If the 'bio_split' path in raid10-read is used while resync/recovery is happening it is possible to deadlock. Fix this be elevating ->nr_waiting for the duration of both parts of the split request. This fixes a bug that has been present since 2.6.22 but has only started manifesting recently for unknown reasons. It is suitable for and -stable since then. Reported-by: Justin Bronder Tested-by: Justin Bronder Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid10.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 42e64e4e5e25..d1d689126346 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -825,11 +825,29 @@ static int make_request(mddev_t *mddev, struct bio * bio) */ bp = bio_split(bio, chunk_sects - (bio->bi_sector & (chunk_sects - 1)) ); + + /* Each of these 'make_request' calls will call 'wait_barrier'. + * If the first succeeds but the second blocks due to the resync + * thread raising the barrier, we will deadlock because the + * IO to the underlying device will be queued in generic_make_request + * and will never complete, so will never reduce nr_pending. + * So increment nr_waiting here so no new raise_barriers will + * succeed, and so the second wait_barrier cannot block. + */ + spin_lock_irq(&conf->resync_lock); + conf->nr_waiting++; + spin_unlock_irq(&conf->resync_lock); + if (make_request(mddev, &bp->bio1)) generic_make_request(&bp->bio1); if (make_request(mddev, &bp->bio2)) generic_make_request(&bp->bio2); + spin_lock_irq(&conf->resync_lock); + conf->nr_waiting--; + wake_up(&conf->wait_barrier); + spin_unlock_irq(&conf->resync_lock); + bio_pair_release(bp); return 0; bad_map: -- cgit v1.2.3 From 5dd8e4f3b39adf9186d7e130a68edc43474fb9f1 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Sun, 8 Aug 2010 16:02:31 +0000 Subject: e100/e1000*/igb*/ixgb*: Add missing read memory barrier commit 2d0bb1c1f4524befe9f0fcf0d0cd3081a451223f upstream. Based on patches from Sonny Rao and Milton Miller... Combined the patches to fix up clean_tx_irq and clean_rx_irq. The PowerPC architecture does not require loads to independent bytes to be ordered without adding an explicit barrier. In ixgbe_clean_rx_irq we load the status bit then load the packet data. With packet split disabled if these loads go out of order we get a stale packet, but we will notice the bad sequence numbers and drop it. The problem occurs with packet split enabled where the TCP/IP header and data are in different descriptors. If the reads go out of order we may have data that doesn't match the TCP/IP header. Since we use hardware checksumming this bad data is never verified and it makes it all the way to the application. This bug was found during stress testing and adding this barrier has been shown to fix it. The bug can manifest as a data integrity issue (bad payload data) or as a BUG in skb_pull(). This was a nasty bug to hunt down, if people agree with the fix I think it's a candidate for stable. Previously Submitted to e1000-devel only for ixgbe http://marc.info/?l=e1000-devel&m=126593062701537&w=3 We've now seen this problem hit with other device drivers (e1000e mostly) So I'm resubmitting with fixes for other Intel Device Drivers with similar issues. CC: Milton Miller CC: Anton Blanchard CC: Sonny Rao Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/e100.c | 2 ++ drivers/net/e1000/e1000_main.c | 3 +++ drivers/net/e1000e/netdev.c | 4 ++++ drivers/net/igb/igb_main.c | 2 ++ drivers/net/igbvf/netdev.c | 2 ++ drivers/net/ixgb/ixgb_main.c | 2 ++ drivers/net/ixgbe/ixgbe_main.c | 1 + drivers/net/ixgbevf/ixgbevf_main.c | 2 ++ 8 files changed, 18 insertions(+) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index b194bad29ace..8e2eab4e7c75 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1779,6 +1779,7 @@ static int e100_tx_clean(struct nic *nic) for (cb = nic->cb_to_clean; cb->status & cpu_to_le16(cb_complete); cb = nic->cb_to_clean = cb->next) { + rmb(); /* read skb after status */ netif_printk(nic, tx_done, KERN_DEBUG, nic->netdev, "cb[%d]->status = 0x%04X\n", (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), @@ -1927,6 +1928,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, netif_printk(nic, rx_status, KERN_DEBUG, nic->netdev, "status=0x%04X\n", rfd_status); + rmb(); /* read size after status bit */ /* If data isn't ready, nothing to indicate */ if (unlikely(!(rfd_status & cb_complete))) { diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 68a80893dce1..a2680bfbc7ad 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3448,6 +3448,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && (count < tx_ring->count)) { bool cleaned = false; + rmb(); /* read buffer_info after eop_desc */ for ( ; !cleaned; count++) { tx_desc = E1000_TX_DESC(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; @@ -3637,6 +3638,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, if (*work_done >= work_to_do) break; (*work_done)++; + rmb(); /* read descriptor and rx_buffer_info after status DD */ status = rx_desc->status; skb = buffer_info->skb; @@ -3843,6 +3845,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, if (*work_done >= work_to_do) break; (*work_done)++; + rmb(); /* read descriptor and rx_buffer_info after status DD */ status = rx_desc->status; skb = buffer_info->skb; diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 79e38dc60a43..ba246793ea4a 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -774,6 +774,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, if (*work_done >= work_to_do) break; (*work_done)++; + rmb(); /* read descriptor and rx_buffer_info after status DD */ status = rx_desc->status; skb = buffer_info->skb; @@ -984,6 +985,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && (count < tx_ring->count)) { bool cleaned = false; + rmb(); /* read buffer_info after eop_desc */ for (; !cleaned; count++) { tx_desc = E1000_TX_DESC(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; @@ -1080,6 +1082,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, break; (*work_done)++; skb = buffer_info->skb; + rmb(); /* read descriptor and rx_buffer_info after status DD */ /* in the packet split case this is header only */ prefetch(skb->data - NET_IP_ALIGN); @@ -1279,6 +1282,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, if (*work_done >= work_to_do) break; (*work_done)++; + rmb(); /* read descriptor and rx_buffer_info after status DD */ status = rx_desc->status; skb = buffer_info->skb; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index df2a6d7c23af..c9cb9c444442 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -5344,6 +5344,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) while ((eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD)) && (count < tx_ring->count)) { + rmb(); /* read buffer_info after eop_desc status */ for (cleaned = false; !cleaned; count++) { tx_desc = E1000_TX_DESC_ADV(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; @@ -5549,6 +5550,7 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector, if (*work_done >= budget) break; (*work_done)++; + rmb(); /* read descriptor and rx_buffer_info after status DD */ skb = buffer_info->skb; prefetch(skb->data - NET_IP_ALIGN); diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index 5e2b2a8c56c6..57b5fee4ca8d 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -248,6 +248,7 @@ static bool igbvf_clean_rx_irq(struct igbvf_adapter *adapter, if (*work_done >= work_to_do) break; (*work_done)++; + rmb(); /* read descriptor and rx_buffer_info after status DD */ buffer_info = &rx_ring->buffer_info[i]; @@ -780,6 +781,7 @@ static bool igbvf_clean_tx_irq(struct igbvf_ring *tx_ring) while ((eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD)) && (count < tx_ring->count)) { + rmb(); /* read buffer_info after eop_desc status */ for (cleaned = false; !cleaned; count++) { tx_desc = IGBVF_TX_DESC_ADV(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index c6b75c83100c..45fc89b9ba64 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1816,6 +1816,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter) while (eop_desc->status & IXGB_TX_DESC_STATUS_DD) { + rmb(); /* read buffer_info after eop_desc */ for (cleaned = false; !cleaned; ) { tx_desc = IXGB_TX_DESC(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; @@ -1976,6 +1977,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter, int *work_done, int work_to_do) break; (*work_done)++; + rmb(); /* read descriptor and rx_buffer_info after status DD */ status = rx_desc->status; skb = buffer_info->skb; buffer_info->skb = NULL; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 74d9b6df3029..649c8678d343 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -748,6 +748,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) && (count < tx_ring->work_limit)) { bool cleaned = false; + rmb(); /* read buffer_info after eop_desc */ for ( ; !cleaned; count++) { struct sk_buff *skb; tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index a16cff7e54a3..3ea59f119951 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -231,6 +231,7 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_adapter *adapter, while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) && (count < tx_ring->work_limit)) { bool cleaned = false; + rmb(); /* read buffer_info after eop_desc */ for ( ; !cleaned; count++) { struct sk_buff *skb; tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); @@ -518,6 +519,7 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, break; (*work_done)++; + rmb(); /* read descriptor and rx_buffer_info after status DD */ if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { hdr_info = le16_to_cpu(ixgbevf_get_hdr_info(rx_desc)); len = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >> -- cgit v1.2.3 From 252eca4afb1580b80bac2fd19138818e59980873 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 23 Jul 2010 15:47:56 -0700 Subject: ioat2: catch and recover from broken vtd configurations v6 commit 556ab45f9a775bfa4762bacc0a4afb5b44b067bc upstream. On some platforms (MacPro3,1) the BIOS assigns the ioatdma device to the incorrect iommu causing faults when the driver initializes. Add a quirk to catch this misconfiguration and try falling back to untranslated operation (which works in the MacPro3,1 case). Assuming there are other platforms with misconfigured iommus teach the ioatdma driver to treat initialization failures as non-fatal (just fail the driver load and emit a warning instead of triggering a BUG_ON). This can be classified as a boot regression since 2.6.32 on affected platforms since the ioatdma module did not autoload prior to that kernel. Acked-by: David Woodhouse Reported-by: Chris Li Tested-by: Chris Li Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/dma/ioat/dma.h | 1 + drivers/dma/ioat/dma_v2.c | 24 ++++++++++++++++++++++-- drivers/dma/ioat/dma_v3.c | 5 ++++- drivers/pci/intel-iommu.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index 6d3a73b57e54..5216c8a92a21 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h @@ -97,6 +97,7 @@ struct ioat_chan_common { #define IOAT_RESET_PENDING 2 #define IOAT_KOBJ_INIT_FAIL 3 #define IOAT_RESHAPE_PENDING 4 + #define IOAT_RUN 5 struct timer_list timer; #define COMPLETION_TIMEOUT msecs_to_jiffies(100) #define IDLE_TIMEOUT msecs_to_jiffies(2000) diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c index 3c8b32a83794..216f9d383b5b 100644 --- a/drivers/dma/ioat/dma_v2.c +++ b/drivers/dma/ioat/dma_v2.c @@ -287,7 +287,10 @@ void ioat2_timer_event(unsigned long data) chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); dev_err(to_dev(chan), "%s: Channel halted (%x)\n", __func__, chanerr); - BUG_ON(is_ioat_bug(chanerr)); + if (test_bit(IOAT_RUN, &chan->state)) + BUG_ON(is_ioat_bug(chanerr)); + else /* we never got off the ground */ + return; } /* if we haven't made progress and we have already @@ -492,6 +495,8 @@ static struct ioat_ring_ent **ioat2_alloc_ring(struct dma_chan *c, int order, gf return ring; } +void ioat2_free_chan_resources(struct dma_chan *c); + /* ioat2_alloc_chan_resources - allocate/initialize ioat2 descriptor ring * @chan: channel to be initialized */ @@ -500,6 +505,7 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) struct ioat2_dma_chan *ioat = to_ioat2_chan(c); struct ioat_chan_common *chan = &ioat->base; struct ioat_ring_ent **ring; + u64 status; int order; /* have we already been set up? */ @@ -540,7 +546,20 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) tasklet_enable(&chan->cleanup_task); ioat2_start_null_desc(ioat); - return 1 << ioat->alloc_order; + /* check that we got off the ground */ + udelay(5); + status = ioat_chansts(chan); + if (is_ioat_active(status) || is_ioat_idle(status)) { + set_bit(IOAT_RUN, &chan->state); + return 1 << ioat->alloc_order; + } else { + u32 chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); + + dev_WARN(to_dev(chan), + "failed to start channel chanerr: %#x\n", chanerr); + ioat2_free_chan_resources(c); + return -EFAULT; + } } bool reshape_ring(struct ioat2_dma_chan *ioat, int order) @@ -778,6 +797,7 @@ void ioat2_free_chan_resources(struct dma_chan *c) del_timer_sync(&chan->timer); device->cleanup_fn((unsigned long) c); device->reset_hw(chan); + clear_bit(IOAT_RUN, &chan->state); spin_lock_bh(&chan->cleanup_lock); spin_lock_bh(&ioat->prep_lock); diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index 1cdd22e1051b..d0f499098479 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -361,7 +361,10 @@ static void ioat3_timer_event(unsigned long data) chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); dev_err(to_dev(chan), "%s: Channel halted (%x)\n", __func__, chanerr); - BUG_ON(is_ioat_bug(chanerr)); + if (test_bit(IOAT_RUN, &chan->state)) + BUG_ON(is_ioat_bug(chanerr)); + else /* we never got off the ground */ + return; } /* if we haven't made progress and we have already diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index c9171be74564..435fbbc2b273 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -3030,6 +3030,34 @@ static void __init iommu_exit_mempool(void) } +static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev) +{ + struct dmar_drhd_unit *drhd; + u32 vtbar; + int rc; + + /* We know that this device on this chipset has its own IOMMU. + * If we find it under a different IOMMU, then the BIOS is lying + * to us. Hope that the IOMMU for this device is actually + * disabled, and it needs no translation... + */ + rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar); + if (rc) { + /* "can't" happen */ + dev_info(&pdev->dev, "failed to run vt-d quirk\n"); + return; + } + vtbar &= 0xffff0000; + + /* we know that the this iommu should be at offset 0xa000 from vtbar */ + drhd = dmar_find_matched_drhd_unit(pdev); + if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000, + TAINT_FIRMWARE_WORKAROUND, + "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n")) + pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO; +} +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu); + static void __init init_no_remapping_devices(void) { struct dmar_drhd_unit *drhd; -- cgit v1.2.3 From 752638f5e4285a42b2df0394c060054f7154c85e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 9 Aug 2010 12:05:43 -0400 Subject: Fix sget() race with failing mount commit 7a4dec53897ecd3367efb1e12fe8a4edc47dc0e9 upstream. If sget() finds a matching superblock being set up, it'll grab an active reference to it and grab s_umount. That's fine - we'll wait for completion of foofs_get_sb() that way. However, if said foofs_get_sb() fails we'll end up holding the halfway-created superblock. deactivate_locked_super() called by foofs_get_sb() will just unlock the sucker since we are holding another active reference to it. What we need is a way to tell if superblock has been successfully set up. Unfortunately, neither ->s_root nor the check for MS_ACTIVE quite fit. Cheap and easy way, suitable for backport: new flag set by the (only) caller of ->get_sb(). If that flag isn't present by the time sget() grabbed s_umount on preexisting superblock it has found, it's seeing a stillborn and should just bury it with deactivate_locked_super() (and repeat the search). Longer term we want to set that flag in ->get_sb() instances (and check for it to distinguish between "sget() found us a live sb" and "sget() has allocated an sb, we need to set it up" in there, instead of checking ->s_root as we do now). Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- fs/namespace.c | 2 +- fs/super.c | 6 ++++++ include/linux/fs.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/namespace.c b/fs/namespace.c index 88058de59c7c..32dcd24bbc9a 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1984,7 +1984,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, if (flags & MS_RDONLY) mnt_flags |= MNT_READONLY; - flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | + flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN | MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT | MS_STRICTATIME); diff --git a/fs/super.c b/fs/super.c index 938119ab8dcb..c7765bd38ee2 100644 --- a/fs/super.c +++ b/fs/super.c @@ -305,8 +305,13 @@ retry: if (s) { up_write(&s->s_umount); destroy_super(s); + s = NULL; } down_write(&old->s_umount); + if (unlikely(!(old->s_flags & MS_BORN))) { + deactivate_locked_super(old); + goto retry; + } return old; } } @@ -909,6 +914,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void goto out_free_secdata; BUG_ON(!mnt->mnt_sb); WARN_ON(!mnt->mnt_sb->s_bdi); + mnt->mnt_sb->s_flags |= MS_BORN; error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata); if (error) diff --git a/include/linux/fs.h b/include/linux/fs.h index 68ca1b0491af..3cdaa57862cb 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -209,6 +209,7 @@ struct inodes_stat_t { #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */ #define MS_I_VERSION (1<<23) /* Update inode I_version field */ #define MS_STRICTATIME (1<<24) /* Always perform atime updates */ +#define MS_BORN (1<<29) #define MS_ACTIVE (1<<30) #define MS_NOUSER (1<<31) -- cgit v1.2.3 From eff3960f25026fbeb854303535974491a5afba13 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Tue, 10 Aug 2010 18:02:55 -0700 Subject: blkdev: cgroup whitelist permission fix commit b7300b78d1a87625975a799a109a2f98d77757c8 upstream. The cgroup device whitelist code gets confused when trying to grant permission to a disk partition that is not currently open. Part of blkdev_open() includes __blkdev_get() on the whole disk. Basically, the only ways to reliably allow a cgroup access to a partition on a block device when using the whitelist are to 1) also give it access to the whole block device or 2) make sure the partition is already open in a different context. The patch avoids the cgroup check for the whole disk case when opening a partition. Addresses https://bugzilla.redhat.com/show_bug.cgi?id=589662 Signed-off-by: Chris Wright Acked-by: Serge E. Hallyn Tested-by: Serge E. Hallyn Reported-by: Vivek Goyal Cc: Al Viro Cc: Christoph Hellwig Cc: "Daniel P. Berrange" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/block_dev.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index b3171fb0dc9a..4c54c86e0289 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1339,10 +1339,12 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) /* * hooks: /n/, see "layering violations". */ - ret = devcgroup_inode_permission(bdev->bd_inode, perm); - if (ret != 0) { - bdput(bdev); - return ret; + if (!for_part) { + ret = devcgroup_inode_permission(bdev->bd_inode, perm); + if (ret != 0) { + bdput(bdev); + return ret; + } } lock_kernel(); -- cgit v1.2.3 From 46c7e62e6b5fd85c82c660249ab411773f6450c1 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Tue, 3 Nov 2009 11:45:11 -0600 Subject: eCryptfs: Handle ioctl calls with unlocked and compat functions commit c43f7b8fb03be8bcc579bfc4e6ab70eac887ab55 upstream. Lower filesystems that only implemented unlocked_ioctl weren't being passed ioctl calls because eCryptfs only checked for lower_file->f_op->ioctl and returned -ENOTTY if it was NULL. eCryptfs shouldn't implement ioctl(), since it doesn't require the BKL. This patch introduces ecryptfs_unlocked_ioctl() and ecryptfs_compat_ioctl(), which passes the calls on to the lower file system. https://bugs.launchpad.net/ecryptfs/+bug/469664 Reported-by: James Dupin Signed-off-by: Tyler Hicks Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/file.c | 56 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index e8fcf4e2ed7d..6e4f84cf73e8 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -292,12 +292,40 @@ static int ecryptfs_fasync(int fd, struct file *file, int flag) return rc; } -static int ecryptfs_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); +static long +ecryptfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct file *lower_file = NULL; + long rc = -ENOTTY; + + if (ecryptfs_file_to_private(file)) + lower_file = ecryptfs_file_to_lower(file); + if (lower_file && lower_file->f_op && lower_file->f_op->unlocked_ioctl) + rc = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg); + return rc; +} + +#ifdef CONFIG_COMPAT +static long +ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct file *lower_file = NULL; + long rc = -ENOIOCTLCMD; + + if (ecryptfs_file_to_private(file)) + lower_file = ecryptfs_file_to_lower(file); + if (lower_file && lower_file->f_op && lower_file->f_op->compat_ioctl) + rc = lower_file->f_op->compat_ioctl(lower_file, cmd, arg); + return rc; +} +#endif const struct file_operations ecryptfs_dir_fops = { .readdir = ecryptfs_readdir, - .ioctl = ecryptfs_ioctl, + .unlocked_ioctl = ecryptfs_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ecryptfs_compat_ioctl, +#endif .open = ecryptfs_open, .flush = ecryptfs_flush, .release = ecryptfs_release, @@ -313,7 +341,10 @@ const struct file_operations ecryptfs_main_fops = { .write = do_sync_write, .aio_write = generic_file_aio_write, .readdir = ecryptfs_readdir, - .ioctl = ecryptfs_ioctl, + .unlocked_ioctl = ecryptfs_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ecryptfs_compat_ioctl, +#endif .mmap = generic_file_mmap, .open = ecryptfs_open, .flush = ecryptfs_flush, @@ -322,20 +353,3 @@ const struct file_operations ecryptfs_main_fops = { .fasync = ecryptfs_fasync, .splice_read = generic_file_splice_read, }; - -static int -ecryptfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - int rc = 0; - struct file *lower_file = NULL; - - if (ecryptfs_file_to_private(file)) - lower_file = ecryptfs_file_to_lower(file); - if (lower_file && lower_file->f_op && lower_file->f_op->ioctl) - rc = lower_file->f_op->ioctl(ecryptfs_inode_to_lower(inode), - lower_file, cmd, arg); - else - rc = -ENOTTY; - return rc; -} -- cgit v1.2.3 From a672b7313b63923f9eb6025adf3c9ef34be00a2a Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo Date: Thu, 29 Jul 2010 13:01:36 +0200 Subject: ecryptfs: release reference to lower mount if interpose fails commit 31f73bee3e170b7cabb35db9e2f4bf7919b9d036 upstream. In ecryptfs_lookup_and_interpose_lower() the lower mount is not decremented if allocation of a dentry info struct failed. As a result the lower filesystem cant be unmounted any more (since it is considered busy). This patch corrects the reference counting. Signed-off-by: Lino Sanfilippo Signed-off-by: Tyler Hicks Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/inode.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 31ef5252f0fe..8cd617b66baa 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -264,7 +264,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, printk(KERN_ERR "%s: Out of memory whilst attempting " "to allocate ecryptfs_dentry_info struct\n", __func__); - goto out_dput; + goto out_put; } ecryptfs_set_dentry_lower(ecryptfs_dentry, lower_dentry); ecryptfs_set_dentry_lower_mnt(ecryptfs_dentry, lower_mnt); @@ -339,8 +339,9 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, out_free_kmem: kmem_cache_free(ecryptfs_header_cache_2, page_virt); goto out; -out_dput: +out_put: dput(lower_dentry); + mntput(lower_mnt); d_drop(ecryptfs_dentry); out: return rc; -- cgit v1.2.3 From 8a7da74a3f365faac6d1bb9b7d5a8d65730aefd6 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 6 Aug 2010 22:58:49 +0200 Subject: fs/ecryptfs/file.c: introduce missing free commit ceeab92971e8af05c1e81a4ff2c271124b55bb9b upstream. The comments in the code indicate that file_info should be released if the function fails. This releasing is done at the label out_free, not out. The semantic match that finds this problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r exists@ local idexpression x; statement S; expression E; identifier f,f1,l; position p1,p2; expression *ptr != NULL; @@ x@p1 = kmem_cache_zalloc(...); ... if (x == NULL) S <... when != x when != if (...) { <+...x...+> } ( x->f1 = E | (x->f1 == NULL || ...) | f(...,x->f1,...) ) ...> ( return <+...x...+>; | return@p2 ...; ) @script:python@ p1 << r.p1; p2 << r.p2; @@ print "* file: %s kmem_cache_zalloc %s" % (p1[0].file,p1[0].line) // Signed-off-by: Julia Lawall Signed-off-by: Tyler Hicks Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 6e4f84cf73e8..622c95140802 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -199,7 +199,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file) "the persistent file for the dentry with name " "[%s]; rc = [%d]\n", __func__, ecryptfs_dentry->d_name.name, rc); - goto out; + goto out_free; } } if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_RDONLY) @@ -207,7 +207,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file) rc = -EPERM; printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs " "file must hence be opened RO\n", __func__); - goto out; + goto out_free; } ecryptfs_set_file_lower( file, ecryptfs_inode_to_private(inode)->lower_file); -- cgit v1.2.3 From d67a13b5b85e843609aac97965bb576544c0555e Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Tue, 29 Jun 2010 17:35:34 +0200 Subject: drbd: Initialize all members of sync_conf to their defaults [Bugz 315] commit 85f4cc17a62c3ac9edeaf120cdae7261df458053 upstream. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/drbd/drbd_main.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 7258c95e895e..16ef66a93eb4 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2660,9 +2660,24 @@ static void drbd_unplug_fn(struct request_queue *q) static void drbd_set_defaults(struct drbd_conf *mdev) { - mdev->sync_conf.after = DRBD_AFTER_DEF; - mdev->sync_conf.rate = DRBD_RATE_DEF; - mdev->sync_conf.al_extents = DRBD_AL_EXTENTS_DEF; + /* This way we get a compile error when sync_conf grows, + and we forgot to initialize it here */ + mdev->sync_conf = (struct syncer_conf) { + /* .rate = */ DRBD_RATE_DEF, + /* .after = */ DRBD_AFTER_DEF, + /* .al_extents = */ DRBD_AL_EXTENTS_DEF, + /* .dp_volume = */ DRBD_DP_VOLUME_DEF, + /* .dp_interval = */ DRBD_DP_INTERVAL_DEF, + /* .throttle_th = */ DRBD_RS_THROTTLE_TH_DEF, + /* .hold_off_th = */ DRBD_RS_HOLD_OFF_TH_DEF, + /* .verify_alg = */ {}, 0, + /* .cpu_mask = */ {}, 0, + /* .csums_alg = */ {}, 0, + /* .use_rle = */ 0 + }; + + /* Have to use that way, because the layout differs between + big endian and little endian */ mdev->state = (union drbd_state) { { .role = R_SECONDARY, .peer = R_UNKNOWN, -- cgit v1.2.3 From cf6fdb61ecc841236ee8047e19ba1773a77850c2 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Mon, 19 Jul 2010 15:04:57 +0200 Subject: drbd: Disable delay probes for the upcomming release commit 6710a5760355be8f2e51682f41b0d3fc76550309 upstream. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/drbd/drbd_main.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 16ef66a93eb4..60bbfcf7fa32 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2371,11 +2371,7 @@ static int _drbd_send_zc_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e) static void consider_delay_probes(struct drbd_conf *mdev) { - if (mdev->state.conn != C_SYNC_SOURCE || mdev->agreed_pro_version < 93) - return; - - if (mdev->dp_volume_last + mdev->sync_conf.dp_volume * 2 < mdev->send_cnt) - drbd_send_delay_probes(mdev); + return; } static int w_delay_probes(struct drbd_conf *mdev, struct drbd_work *w, int cancel) -- cgit v1.2.3 From bd388a58b5243cce7fad0c5f8e8586c6f9a02081 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 3 Aug 2010 13:14:33 +0200 Subject: bio, fs: update RWA_MASK, READA and SWRITE to match the corresponding BIO_RW_* bits commit aca27ba9618276dd2f777bcd5a1419589ccf1ca8 upstream. Commit a82afdf (block: use the same failfast bits for bio and request) moved BIO_RW_* bits around such that they match up with REQ_* bits. Unfortunately, fs.h hard coded RW_MASK, RWA_MASK, READ, WRITE, READA and SWRITE as 0, 1, 2 and 3, and expected them to match with BIO_RW_* bits. READ/WRITE didn't change but BIO_RW_AHEAD was moved to bit 4 instead of bit 1, breaking RWA_MASK, READA and SWRITE. This patch updates RWA_MASK, READA and SWRITE such that they match the BIO_RW_* bits again. A follow up patch will update the definitions to directly use BIO_RW_* bits so that this kind of breakage won't happen again. Neil also spotted missing RWA_MASK conversion. Stable: The offending commit a82afdf was released with v2.6.32, so this patch should be applied to all kernels since then but it must _NOT_ be applied to kernels earlier than that. Signed-off-by: Tejun Heo Reported-and-bisected-by: Vladislav Bolkhovitin Root-caused-by: Neil Brown Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- include/linux/fs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 3cdaa57862cb..f0f447aed647 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -145,11 +145,11 @@ struct inodes_stat_t { * */ #define RW_MASK 1 -#define RWA_MASK 2 +#define RWA_MASK 16 #define READ 0 #define WRITE 1 -#define READA 2 /* read-ahead - don't block if no resources */ -#define SWRITE 3 /* for ll_rw_block() - wait for buffer lock */ +#define READA 16 /* readahead - don't block if no resources */ +#define SWRITE 17 /* for ll_rw_block(), wait for buffer lock */ #define READ_SYNC (READ | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG)) #define READ_META (READ | (1 << BIO_RW_META)) #define WRITE_SYNC_PLUG (WRITE | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_NOIDLE)) -- cgit v1.2.3 From d774a312e59179db06d61d916f096fa241545e59 Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Tue, 10 Aug 2010 18:03:08 -0700 Subject: signalfd: fill in ssi_int for posix timers and message queues commit a2a20c412c86e0bb46a9ab0dd31bcfe6d201b913 upstream. If signalfd is used to consume a signal generated by a POSIX interval timer or POSIX message queue, the ssi_int field does not reflect the data (sigevent->sigev_value) supplied to timer_create(2) or mq_notify(3). (The ssi_ptr field, however, is filled in.) This behavior differs from signalfd's treatment of sigqueue-generated signals -- see the default case in signalfd_copyinfo. It also gives results that differ from the case when a signal is handled conventionally via a sigaction-registered handler. So, set signalfd_siginfo->ssi_int in the remaining cases (__SI_TIMER, __SI_MESGQ) where ssi_ptr is set. akpm: a non-back-compatible change. Merge into -stable to minimise the number of kernels which are in the field and which miss this feature. Signed-off-by: Nathan Lynch Acked-by: Davide Libenzi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/signalfd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/signalfd.c b/fs/signalfd.c index f329849ce3c0..1c5a6add779d 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c @@ -88,6 +88,7 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, err |= __put_user(kinfo->si_tid, &uinfo->ssi_tid); err |= __put_user(kinfo->si_overrun, &uinfo->ssi_overrun); err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr); + err |= __put_user(kinfo->si_int, &uinfo->ssi_int); break; case __SI_POLL: err |= __put_user(kinfo->si_band, &uinfo->ssi_band); @@ -111,6 +112,7 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid); err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid); err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr); + err |= __put_user(kinfo->si_int, &uinfo->ssi_int); break; default: /* -- cgit v1.2.3 From c53f89ac7b1b89a7132e59a1a8dc548eaeb10556 Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Tue, 20 Jul 2010 10:58:52 +0300 Subject: pxa/cm-x300: fix ffuart registration commit a6cd7eb374647b572ae9e7dbfe49871e6996e8e0 upstream. ffuart is available on cm-x300 only with pxa300. Signed-off-by: Igor Grinberg Signed-off-by: Eric Miao Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-pxa/cm-x300.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index fdda6be6c391..d717b49f0172 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -745,9 +745,10 @@ static void __init cm_x300_init(void) { cm_x300_init_mfp(); - pxa_set_ffuart_info(NULL); pxa_set_btuart_info(NULL); pxa_set_stuart_info(NULL); + if (cpu_is_pxa300()) + pxa_set_ffuart_info(NULL); cm_x300_init_da9030(); cm_x300_init_dm9000(); -- cgit v1.2.3 From 3e3c8c718ecf07b641b4d21a5d5ba259911a731b Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 19 Jul 2010 13:36:21 -0700 Subject: smsc911x: Add spinlocks around registers access commit 492c5d943d6a04b124ba3a719dc746dc36b14cfb upstream. On SMP systems, the SMSC911x registers may be accessed by multiple CPUs and this seems to put the chip in an inconsistent state. The patch adds spinlocks to the smsc911x_reg_read, smsc911x_reg_write, smsc911x_rx_readfifo and smsc911x_tx_writefifo functions. Signed-off-by: Catalin Marinas Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/smsc911x.c | 92 ++++++++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index cc559741b0fa..7a7b01a0fff8 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -84,8 +84,7 @@ struct smsc911x_data { */ spinlock_t mac_lock; - /* spinlock to ensure 16-bit accesses are serialised. - * unused with a 32-bit bus */ + /* spinlock to ensure register accesses are serialised */ spinlock_t dev_lock; struct phy_device *phy_dev; @@ -118,37 +117,33 @@ struct smsc911x_data { unsigned int hashlo; }; -/* The 16-bit access functions are significantly slower, due to the locking - * necessary. If your bus hardware can be configured to do this for you - * (in response to a single 32-bit operation from software), you should use - * the 32-bit access functions instead. */ - -static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg) +static inline u32 __smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg) { if (pdata->config.flags & SMSC911X_USE_32BIT) return readl(pdata->ioaddr + reg); - if (pdata->config.flags & SMSC911X_USE_16BIT) { - u32 data; - unsigned long flags; - - /* these two 16-bit reads must be performed consecutively, so - * must not be interrupted by our own ISR (which would start - * another read operation) */ - spin_lock_irqsave(&pdata->dev_lock, flags); - data = ((readw(pdata->ioaddr + reg) & 0xFFFF) | + if (pdata->config.flags & SMSC911X_USE_16BIT) + return ((readw(pdata->ioaddr + reg) & 0xFFFF) | ((readw(pdata->ioaddr + reg + 2) & 0xFFFF) << 16)); - spin_unlock_irqrestore(&pdata->dev_lock, flags); - - return data; - } BUG(); return 0; } -static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg, - u32 val) +static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg) +{ + u32 data; + unsigned long flags; + + spin_lock_irqsave(&pdata->dev_lock, flags); + data = __smsc911x_reg_read(pdata, reg); + spin_unlock_irqrestore(&pdata->dev_lock, flags); + + return data; +} + +static inline void __smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg, + u32 val) { if (pdata->config.flags & SMSC911X_USE_32BIT) { writel(val, pdata->ioaddr + reg); @@ -156,44 +151,54 @@ static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg, } if (pdata->config.flags & SMSC911X_USE_16BIT) { - unsigned long flags; - - /* these two 16-bit writes must be performed consecutively, so - * must not be interrupted by our own ISR (which would start - * another read operation) */ - spin_lock_irqsave(&pdata->dev_lock, flags); writew(val & 0xFFFF, pdata->ioaddr + reg); writew((val >> 16) & 0xFFFF, pdata->ioaddr + reg + 2); - spin_unlock_irqrestore(&pdata->dev_lock, flags); return; } BUG(); } +static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg, + u32 val) +{ + unsigned long flags; + + spin_lock_irqsave(&pdata->dev_lock, flags); + __smsc911x_reg_write(pdata, reg, val); + spin_unlock_irqrestore(&pdata->dev_lock, flags); +} + /* Writes a packet to the TX_DATA_FIFO */ static inline void smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf, unsigned int wordcount) { + unsigned long flags; + + spin_lock_irqsave(&pdata->dev_lock, flags); + if (pdata->config.flags & SMSC911X_SWAP_FIFO) { while (wordcount--) - smsc911x_reg_write(pdata, TX_DATA_FIFO, swab32(*buf++)); - return; + __smsc911x_reg_write(pdata, TX_DATA_FIFO, + swab32(*buf++)); + goto out; } if (pdata->config.flags & SMSC911X_USE_32BIT) { writesl(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount); - return; + goto out; } if (pdata->config.flags & SMSC911X_USE_16BIT) { while (wordcount--) - smsc911x_reg_write(pdata, TX_DATA_FIFO, *buf++); - return; + __smsc911x_reg_write(pdata, TX_DATA_FIFO, *buf++); + goto out; } BUG(); +out: + spin_unlock_irqrestore(&pdata->dev_lock, flags); } /* Reads a packet out of the RX_DATA_FIFO */ @@ -201,24 +206,31 @@ static inline void smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf, unsigned int wordcount) { + unsigned long flags; + + spin_lock_irqsave(&pdata->dev_lock, flags); + if (pdata->config.flags & SMSC911X_SWAP_FIFO) { while (wordcount--) - *buf++ = swab32(smsc911x_reg_read(pdata, RX_DATA_FIFO)); - return; + *buf++ = swab32(__smsc911x_reg_read(pdata, + RX_DATA_FIFO)); + goto out; } if (pdata->config.flags & SMSC911X_USE_32BIT) { readsl(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount); - return; + goto out; } if (pdata->config.flags & SMSC911X_USE_16BIT) { while (wordcount--) - *buf++ = smsc911x_reg_read(pdata, RX_DATA_FIFO); - return; + *buf++ = __smsc911x_reg_read(pdata, RX_DATA_FIFO); + goto out; } BUG(); +out: + spin_unlock_irqrestore(&pdata->dev_lock, flags); } /* waits for MAC not busy, with timeout. Only called by smsc911x_mac_read -- cgit v1.2.3 From 2997ccb85bbe66673346813d78f125af4d002c31 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 5 Aug 2010 11:20:51 +0100 Subject: ARM: 6299/1: errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID commit cdf357f1e13a08a11261edacb3083746f65c1ed9 upstream. On versions of the Cortex-A9 prior to r2p0, performing TLB invalidations by ASID match can result in the incorrect ASID being broadcast to other CPUs. As a consequence of this, the targetted TLB entries are not invalidated across the system. This workaround changes the TLB flushing routines to invalidate entries regardless of the ASID. Tested-by: Rob Clark Acked-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/Kconfig | 12 ++++++++++++ arch/arm/include/asm/tlbflush.h | 8 ++++++++ 2 files changed, 20 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 98922f7d2d12..4824fb4f4019 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1027,6 +1027,18 @@ config PL310_ERRATA_588369 is not correctly implemented in PL310 as clean lines are not invalidated as a result of these operations. Note that this errata uses Texas Instrument's secure monitor api. + +config ARM_ERRATA_720789 + bool "ARM errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID" + depends on CPU_V7 && SMP + help + This option enables the workaround for the 720789 Cortex-A9 (prior to + r2p0) erratum. A faulty ASID can be sent to the other CPUs for the + broadcasted CP15 TLB maintenance operations TLBIASIDIS and TLBIMVAIS. + As a consequence of this erratum, some TLB entries which should be + invalidated are not, resulting in an incoherency in the system page + tables. The workaround changes the TLB flushing routines to invalidate + entries regardless of the ASID. endmenu source "arch/arm/common/Kconfig" diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h index bd863d8608cd..33b546ae72d4 100644 --- a/arch/arm/include/asm/tlbflush.h +++ b/arch/arm/include/asm/tlbflush.h @@ -378,7 +378,11 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm) if (tlb_flag(TLB_V6_I_ASID)) asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc"); if (tlb_flag(TLB_V7_UIS_ASID)) +#ifdef CONFIG_ARM_ERRATA_720789 + asm("mcr p15, 0, %0, c8, c3, 0" : : "r" (zero) : "cc"); +#else asm("mcr p15, 0, %0, c8, c3, 2" : : "r" (asid) : "cc"); +#endif if (tlb_flag(TLB_BTB)) { /* flush the branch target cache */ @@ -424,7 +428,11 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) if (tlb_flag(TLB_V6_I_PAGE)) asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc"); if (tlb_flag(TLB_V7_UIS_PAGE)) +#ifdef CONFIG_ARM_ERRATA_720789 + asm("mcr p15, 0, %0, c8, c3, 3" : : "r" (uaddr & PAGE_MASK) : "cc"); +#else asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (uaddr) : "cc"); +#endif if (tlb_flag(TLB_BTB)) { /* flush the branch target cache */ -- cgit v1.2.3 From 5605a6f71afc6e76f9ef7d6e18dd042024bc4f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 2 Aug 2010 08:32:22 +0100 Subject: ARM: 6280/1: imx: Fix build failure when including without MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 868003ca7ad17ac6c1606dc36101f10a7825b399 upstream. This is a follow up to 14cb0de (arm/imx/gpio: add spinlock protection) and fixes the following build failure: CC arch/arm/mach-imx/pcm970-baseboard.o In file included from arch/arm/include/asm/gpio.h:6, from include/linux/gpio.h:8, from arch/arm/mach-imx/pcm970-baseboard.c:20: arch/arm/plat-mxc/include/mach/gpio.h:40: error: expected specifier-qualifier-list before 'spinlock_t' Signed-off-by: Uwe Kleine-König Signed-off-by: Russell King --- arch/arm/plat-mxc/include/mach/gpio.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h index 6bd932c3e4e3..7a0dc5aa2479 100644 --- a/arch/arm/plat-mxc/include/mach/gpio.h +++ b/arch/arm/plat-mxc/include/mach/gpio.h @@ -19,6 +19,7 @@ #ifndef __ASM_ARCH_MXC_GPIO_H__ #define __ASM_ARCH_MXC_GPIO_H__ +#include #include #include -- cgit v1.2.3 From 63d0b4fd495af6b8fba0b8f5a2fccb81acf44e3f Mon Sep 17 00:00:00 2001 From: Anand Gadiyar Date: Thu, 8 Jul 2010 14:02:59 +0530 Subject: USB: musb: use correct register widths in register dumps commit 0936fb5e92a90476959447ad8ae5d780afbbd930 upstream. DMA_ADDR and DMA_COUNT are 32-bit registers, not 16-bit. Marking them as 16-bit in the table causes only the lower 16-bits to be dumped and this is misleading. Signed-off-by: Anand Gadiyar Acked-by: Felipe Balbi Signed-off-by: Ajay Kumar Gupta Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_debugfs.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c index bba76af0c0c6..c79a5e30d437 100644 --- a/drivers/usb/musb/musb_debugfs.c +++ b/drivers/usb/musb/musb_debugfs.c @@ -92,29 +92,29 @@ static const struct musb_register_map musb_regmap[] = { { "LS_EOF1", 0x7E, 8 }, { "SOFT_RST", 0x7F, 8 }, { "DMA_CNTLch0", 0x204, 16 }, - { "DMA_ADDRch0", 0x208, 16 }, - { "DMA_COUNTch0", 0x20C, 16 }, + { "DMA_ADDRch0", 0x208, 32 }, + { "DMA_COUNTch0", 0x20C, 32 }, { "DMA_CNTLch1", 0x214, 16 }, - { "DMA_ADDRch1", 0x218, 16 }, - { "DMA_COUNTch1", 0x21C, 16 }, + { "DMA_ADDRch1", 0x218, 32 }, + { "DMA_COUNTch1", 0x21C, 32 }, { "DMA_CNTLch2", 0x224, 16 }, - { "DMA_ADDRch2", 0x228, 16 }, - { "DMA_COUNTch2", 0x22C, 16 }, + { "DMA_ADDRch2", 0x228, 32 }, + { "DMA_COUNTch2", 0x22C, 32 }, { "DMA_CNTLch3", 0x234, 16 }, - { "DMA_ADDRch3", 0x238, 16 }, - { "DMA_COUNTch3", 0x23C, 16 }, + { "DMA_ADDRch3", 0x238, 32 }, + { "DMA_COUNTch3", 0x23C, 32 }, { "DMA_CNTLch4", 0x244, 16 }, - { "DMA_ADDRch4", 0x248, 16 }, - { "DMA_COUNTch4", 0x24C, 16 }, + { "DMA_ADDRch4", 0x248, 32 }, + { "DMA_COUNTch4", 0x24C, 32 }, { "DMA_CNTLch5", 0x254, 16 }, - { "DMA_ADDRch5", 0x258, 16 }, - { "DMA_COUNTch5", 0x25C, 16 }, + { "DMA_ADDRch5", 0x258, 32 }, + { "DMA_COUNTch5", 0x25C, 32 }, { "DMA_CNTLch6", 0x264, 16 }, - { "DMA_ADDRch6", 0x268, 16 }, - { "DMA_COUNTch6", 0x26C, 16 }, + { "DMA_ADDRch6", 0x268, 32 }, + { "DMA_COUNTch6", 0x26C, 32 }, { "DMA_CNTLch7", 0x274, 16 }, - { "DMA_ADDRch7", 0x278, 16 }, - { "DMA_COUNTch7", 0x27C, 16 }, + { "DMA_ADDRch7", 0x278, 32 }, + { "DMA_COUNTch7", 0x27C, 32 }, { } /* Terminating Entry */ }; -- cgit v1.2.3 From a6b37a9ed03585d0e1e132d424569003be2abba2 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 14 Jul 2010 11:03:23 -0400 Subject: USB: EHCI: remove PCI assumption commit ae68a83bdc1971cb02fefc7a686ba6d077065e71 upstream. This patch (as1405) fixes a small bug in ehci-hcd's isochronous scheduler. Not all EHCI controllers are PCI, and the code shouldn't assume that they are. Instead, introduce a special flag for controllers which need to delay iso scheduling for full-speed devices beyond the scheduling threshold. Signed-off-by: Alan Stern CC: Sarah Sharp CC: David Brownell Acked-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-pci.c | 1 + drivers/usb/host/ehci-sched.c | 10 ++++------ drivers/usb/host/ehci.h | 1 + 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index d43d176161aa..19f5070d5c48 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -114,6 +114,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) break; case PCI_VENDOR_ID_INTEL: ehci->need_io_watchdog = 0; + ehci->fs_i_thresh = 1; if (pdev->device == 0x27cc) { ehci->broken_periodic = 1; ehci_info(ehci, "using broken periodic workaround\n"); diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 805ec633a652..93f58e52503b 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1400,7 +1400,6 @@ iso_stream_schedule ( int status; unsigned mod = ehci->periodic_size << 3; struct ehci_iso_sched *sched = urb->hcpriv; - struct pci_dev *pdev; if (sched->span > (mod - SCHEDULE_SLOP)) { ehci_dbg (ehci, "iso request %p too long\n", urb); @@ -1427,15 +1426,14 @@ iso_stream_schedule ( * slot in the schedule, implicitly assuming URB_ISO_ASAP. */ if (likely (!list_empty (&stream->td_list))) { - pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); start = stream->next_uframe; /* For high speed devices, allow scheduling within the - * isochronous scheduling threshold. For full speed devices, - * don't. (Work around for Intel ICH9 bug.) + * isochronous scheduling threshold. For full speed devices + * and Intel PCI-based controllers, don't (work around for + * Intel ICH9 bug). */ - if (!stream->highspeed && - pdev->vendor == PCI_VENDOR_ID_INTEL) + if (!stream->highspeed && ehci->fs_i_thresh) next = now + ehci->i_thresh; else next = now; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 650a687f2854..8b3d9c8f33ef 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -130,6 +130,7 @@ struct ehci_hcd { /* one per controller */ unsigned has_amcc_usb23:1; unsigned need_io_watchdog:1; unsigned broken_periodic:1; + unsigned fs_i_thresh:1; /* Intel iso scheduling */ /* required for usb32 quirk */ #define OHCI_CTRL_HCFS (3 << 6) -- cgit v1.2.3 From 064b8f10414d51ae972f80518e320dc5cff9f1f8 Mon Sep 17 00:00:00 2001 From: Steven Robertson Date: Wed, 21 Jul 2010 16:38:44 -0400 Subject: USB: resizing usbmon binary interface buffer causes protection faults commit 33d973ad88ceb83ed1449592b7574b5b5bb33ac6 upstream. Enlarging the buffer size via the MON_IOCT_RING_SIZE ioctl causes general protection faults. It appears the culprit is an incorrect argument to mon_free_buff: instead of passing the size of the current buffer being freed, the size of the new buffer is passed. Use the correct size argument to mon_free_buff when changing the size of the buffer. Signed-off-by: Steven Robertson Acked-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/mon/mon_bin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 61c76b13f0f1..56c93cac24c1 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -1009,7 +1009,7 @@ static int mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) mutex_lock(&rp->fetch_lock); spin_lock_irqsave(&rp->b_lock, flags); - mon_free_buff(rp->b_vec, size/CHUNK_SIZE); + mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE); kfree(rp->b_vec); rp->b_vec = vec; rp->b_size = size; -- cgit v1.2.3 From 9bb40fbf5c377ff06a03d090b07f5287ed2fc82e Mon Sep 17 00:00:00 2001 From: Phil Dibowitz Date: Thu, 22 Jul 2010 00:05:01 +0200 Subject: USB delay init quirk for logitech Harmony 700-series devices commit 93362a875fc69881ae69299efaf19a55a1f57db0 upstream. The Logitech Harmony 700 series needs an extra delay during initialization. This patch adds a USB quirk which enables such a delay and adds the device to the quirks list. Signed-off-by: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 6 +++++- drivers/usb/core/quirks.c | 3 +++ include/linux/usb/quirks.h | 4 ++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 70cccc75a362..ffc80e3241e1 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -1801,7 +1802,6 @@ int usb_new_device(struct usb_device *udev) pm_runtime_set_active(&udev->dev); pm_runtime_enable(&udev->dev); - usb_detect_quirks(udev); err = usb_enumerate_device(udev); /* Read descriptors */ if (err < 0) goto fail; @@ -3111,6 +3111,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, if (status < 0) goto loop; + usb_detect_quirks(udev); + if (udev->quirks & USB_QUIRK_DELAY_INIT) + msleep(1000); + /* consecutive bus-powered hubs aren't reliable; they can * violate the voltage drop budget. if the new child has * a "powered" LED, users should notice we didn't enable it diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index db99c084df92..25719da45e33 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -38,6 +38,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* Creative SB Audigy 2 NX */ { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Logitech Harmony 700-series */ + { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, + /* Philips PSC805 audio device */ { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME }, diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h index 16b7f3347545..3e93de7ecbc3 100644 --- a/include/linux/usb/quirks.h +++ b/include/linux/usb/quirks.h @@ -26,4 +26,8 @@ and can't handle talking to these interfaces */ #define USB_QUIRK_HONOR_BNUMINTERFACES 0x00000020 +/* device needs a pause during initialization, after we read the device + descriptor */ +#define USB_QUIRK_DELAY_INIT 0x00000040 + #endif /* __LINUX_USB_QUIRKS_H */ -- cgit v1.2.3 From a553041b816b047b82739270a202ec1a347e8b91 Mon Sep 17 00:00:00 2001 From: "John G. Rogers" Date: Sat, 24 Jul 2010 09:50:52 -0400 Subject: USB: serial: enabling support for Segway RMP in ftdi_sio commit afad19648f70c6493193e0a774bd754b7790b4a0 upstream. I have added the ProductID=0xe729 VendorID=FTDI_VID=0x0403 which will enable support for the Segway Robotic Mobility Platform (RMP200) in the ftdi_sio kernel module. Currently, users of the Segway RMP200 must use a RUN+="/sbin/modprobe -q ftdi-sio product=0xe729 vendor=0x0403 in a udev rule to get the ftdi_sio module to handle the usb interface and mount it on /dev/ttyXXX. This is not a good solution because some users will have multiple USB to Serial converters which will use the ftdi_sio module. Signed-off-by: John Rogers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index e298dc4baed7..a3671dbcdd49 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -746,6 +746,7 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index d01946db8fac..74f094273f79 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1032,3 +1032,8 @@ #define XVERVE_SIGNALYZER_SH2_PID 0xBCA2 #define XVERVE_SIGNALYZER_SH4_PID 0xBCA4 +/* + * Segway Robotic Mobility Platform USB interface (using VID 0x0403) + * Submitted by John G. Rogers + */ +#define SEGWAY_RMP200_PID 0xe729 -- cgit v1.2.3 From 13ffcb8f796f5e7830e3620aeb12d9cd6bc7b75c Mon Sep 17 00:00:00 2001 From: Pavel Kazlou Date: Thu, 22 Jul 2010 03:22:20 +0300 Subject: USB: option: Huawei ETS 1220 support added commit b972302b0a13aaddc9e90da2b4b52722e5d0e776 upstream. The patch adds Huawei ETS 1220 product id into the list of supported devices in 'option' usb serial driver. Signed-off-by: Pavel Kazlou Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5cd30e4345c6..c7fa0856aae2 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -146,6 +146,7 @@ static void option_instat_callback(struct urb *urb); #define HUAWEI_PRODUCT_E143E 0x143E #define HUAWEI_PRODUCT_E143F 0x143F #define HUAWEI_PRODUCT_E14AC 0x14AC +#define HUAWEI_PRODUCT_ETS1220 0x1803 #define QUANTA_VENDOR_ID 0x0408 #define QUANTA_PRODUCT_Q101 0xEA02 @@ -482,6 +483,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */ -- cgit v1.2.3 From ee567603665c2dfbc57652dd0cd6fc877b556da1 Mon Sep 17 00:00:00 2001 From: Andrew Bird Date: Fri, 23 Jul 2010 16:04:41 +0100 Subject: USB: option: add huawei k3765 k4505 devices to work properly commit 0372a754be9aa43e19fd86c9bc04796d43b55e38 upstream. This patch adds the product IDs of Huawei's K3765 and K4505 mobile broadband usb modems to option.c. It also adds a quirk to the option probe function so that binding to the device's network interface(class 0xff) is avoided. This is necessary to allow another driver to bind to that, and to avoid programs like wvdial opening a nonfunctioning tty during modem discovery. Signed-off-by: Andrew Bird Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index c7fa0856aae2..5c35b3a7082a 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -145,6 +145,8 @@ static void option_instat_callback(struct urb *urb); #define HUAWEI_PRODUCT_E143D 0x143D #define HUAWEI_PRODUCT_E143E 0x143E #define HUAWEI_PRODUCT_E143F 0x143F +#define HUAWEI_PRODUCT_K4505 0x1464 +#define HUAWEI_PRODUCT_K3765 0x1465 #define HUAWEI_PRODUCT_E14AC 0x14AC #define HUAWEI_PRODUCT_ETS1220 0x1803 @@ -483,6 +485,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) }, @@ -1019,6 +1023,13 @@ static int option_probe(struct usb_serial *serial, serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff) return -ENODEV; + /* Don't bind network interfaces on Huawei K3765 & K4505 */ + if (serial->dev->descriptor.idVendor == HUAWEI_VENDOR_ID && + (serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K3765 || + serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4505) && + serial->interface->cur_altsetting->desc.bInterfaceNumber == 1) + return -ENODEV; + data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); if (!data) -- cgit v1.2.3 From ebc56bdd089aee17c26a743bdac311f33bb4d6f8 Mon Sep 17 00:00:00 2001 From: "dranch@trinnet.net" Date: Mon, 26 Jul 2010 19:44:33 -0700 Subject: USB: ftdi_sio: device id for Navitator commit b6180ef7c99574c3350bbffa2a3a9d675321543d upstream. This patch is to add a US Interface, Inc. "Navigator" USB device. Specifically, it's a HAM Radio USB sound modem that also incorporates three pairs of unique FTDI serial ports. The standard Linux FTDI serial driver will only recognize the first two serial ports of an unknown FDTI derived device and this patch adds in recognition to these specific new IDs. Signed-off-by: David A. Ranch Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 3 +++ drivers/usb/serial/ftdi_sio_ids.h | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index a3671dbcdd49..eb12d9b096b4 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -157,6 +157,9 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_5_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_6_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_7_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_USINT_CAT_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_USINT_WKEY_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_USINT_RS232_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 74f094273f79..6e612c52e763 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -40,6 +40,11 @@ #define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */ +/* US Interface Navigator (http://www.usinterface.com/) */ +#define FTDI_USINT_CAT_PID 0xb810 /* Navigator CAT and 2nd PTT lines */ +#define FTDI_USINT_WKEY_PID 0xb811 /* Navigator WKEY and FSK lines */ +#define FTDI_USINT_RS232_PID 0xb812 /* Navigator RS232 and CONFIG lines */ + /* OOCDlink by Joern Kaipf * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */ #define FTDI_OOCDLINK_PID 0xbaf8 /* Amontec JTAGkey */ -- cgit v1.2.3 From 9a03bd19ebde91a965f105e95225fc0fad351ea5 Mon Sep 17 00:00:00 2001 From: Alessio Igor Bogani Date: Tue, 27 Jul 2010 23:05:14 +0200 Subject: USB: cp210x: Add four new device IDs commit 356c5a4834a74c621715f7a7f16ded914eecbd3c upstream. Signed-off-by: Alessio Igor Bogani Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 8b8c7976b4c0..2bef4415c19c 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -126,6 +126,10 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ + { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */ + { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ + { USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */ + { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ { } /* Terminating Entry */ }; -- cgit v1.2.3 From 733677e180eb390067ae5f53ef9ff7396aa8a07b Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Mon, 2 Aug 2010 22:09:01 +0800 Subject: USB: usbtest: avoid to free coherent buffer in atomic context commit e10e1bec8e6654de4591ef45ddd6a6d1e5b2591c upstream. This patch fixes the warning below: [30753.755998] ------------[ cut here ]------------ [30753.755998] WARNING: at /home/tom/git/linux-2.6/linux-2.6-next/arch/x86/include/asm/dma-mapping.h:155 hcd_buffer_free+0xb1/0xd4 [usbcore]() [30753.755998] Hardware name: 6475EK2 [30753.755998] Modules linked in: uvcvideo ehci_hcd usbtest cdc_ether usbnet vfat fat usb_storage nfsd lockd nfs_acl auth_rpcgss exportfs mii tun videodev v4l1_compat v4l2_compat_ioctl32 fuse bridge stp llc sunrpc ipv6 cpufreq_ondemand acpi_cpufreq freq_table mperf kvm_intel kvm arc4 ecb ath5k usbhid mac80211 snd_hda_codec_conexant ch341 usbserial ath cfg80211 thinkpad_acpi snd_hda_intel pcspkr wmi hwmon yenta_socket iTCO_wdt iTCO_vendor_support i2c_i801 e1000e snd_hda_codec snd_hwdep snd_pcm snd_timer snd soundcore snd_page_alloc pata_acpi uhci_hcd ohci_hcd usbcore i915 drm_kms_helper drm i2c_algo_bit i2c_core video output [last unloaded: uvcvideo] [30753.755998] Pid: 0, comm: swapper Tainted: G W 2.6.35-rc6-gkh-wl+ #49 [30753.755998] Call Trace: [30753.755998] [] warn_slowpath_common+0x80/0x98 [30753.755998] [] warn_slowpath_null+0x15/0x17 [30753.755998] [] hcd_buffer_free+0xb1/0xd4 [usbcore] [30753.755998] [] usb_free_coherent+0x1c/0x1e [usbcore] [30753.755998] [] simple_free_urb+0x23/0x2f [usbtest] [30753.755998] [] iso_callback+0xbb/0x10f [usbtest] [30753.755998] [] usb_hcd_giveback_urb+0x8c/0xc0 [usbcore] [30753.755998] [] ehci_urb_done+0x84/0x95 [ehci_hcd] [30753.755998] [] ehci_work+0x41a/0x7dd [ehci_hcd] [30753.755998] [] ehci_irq+0x33b/0x370 [ehci_hcd] [30753.755998] [] ? sched_clock+0x9/0xd [30753.755998] [] ? sched_clock_local+0x1c/0x82 [30753.755998] [] ? sched_clock_cpu+0xc3/0xce [30753.755998] [] ? trace_hardirqs_off+0xd/0xf [30753.755998] [] ? cpu_clock+0x43/0x5e [30753.755998] [] usb_hcd_irq+0x45/0xa1 [usbcore] [30753.755998] [] handle_IRQ_event+0x20/0xa5 [30753.755998] [] handle_fasteoi_irq+0x92/0xd2 [30753.755998] [] handle_irq+0x1f/0x2a [30753.755998] [] do_IRQ+0x57/0xbe [30753.755998] [] ret_from_intr+0x0/0x16 [30753.755998] [] ? acpi_idle_enter_bm+0x231/0x269 [30753.755998] [] ? acpi_idle_enter_bm+0x22a/0x269 [30753.755998] [] cpuidle_idle_call+0x99/0xce [30753.755998] [] cpu_idle+0x61/0xaa [30753.755998] [] start_secondary+0x1c2/0x1c6 [30753.755998] ---[ end trace 904cfaf7ab4cb1a2 ]--- Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbtest.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 16dffe99d9f1..c3049c7cc8ed 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -1378,7 +1378,6 @@ static void iso_callback (struct urb *urb) break; } } - simple_free_urb (urb); ctx->pending--; if (ctx->pending == 0) { @@ -1495,6 +1494,7 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, } simple_free_urb (urbs [i]); + urbs[i] = NULL; context.pending--; context.submit_error = 1; break; @@ -1504,6 +1504,10 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, wait_for_completion (&context.done); + for (i = 0; i < param->sglen; i++) { + if (urbs[i]) + simple_free_urb(urbs[i]); + } /* * Isochronous transfers are expected to fail sometimes. As an * arbitrary limit, we will report an error if any submissions -- cgit v1.2.3 From 8762dc2878fcdab3a3d71502c42e5923c79e8086 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 3 Aug 2010 02:32:28 +0200 Subject: USB: fix thread-unsafe anchor utiliy routines commit b3e670443b7fb8a2d29831b62b44a039c283e351 upstream. This patch fixes a race condition in two utility routines related to the removal/unlinking of urbs from an anchor. If two threads are concurrently accessing the same anchor, both could end up with the same urb - thinking they are the exclusive owner. Alan Stern pointed out a related issue in usb_unlink_anchored_urbs: "The URB isn't removed from the anchor until it completes (as a by-product of completion, in fact), which might not be for quite some time after the unlink call returns. In the meantime, the subroutine will keep trying to unlink it, over and over again." Cc: Oliver Neukum Cc: Greg Kroah-Hartman Acked-by: Alan Stern Signed-off-by: Christian Lamparter Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/urb.c | 50 +++++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 7c0555548ac8..419e6b34e2fe 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -137,6 +137,16 @@ void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor) } EXPORT_SYMBOL_GPL(usb_anchor_urb); +/* Callers must hold anchor->lock */ +static void __usb_unanchor_urb(struct urb *urb, struct usb_anchor *anchor) +{ + urb->anchor = NULL; + list_del(&urb->anchor_list); + usb_put_urb(urb); + if (list_empty(&anchor->urb_list)) + wake_up(&anchor->wait); +} + /** * usb_unanchor_urb - unanchors an URB * @urb: pointer to the urb to anchor @@ -156,17 +166,14 @@ void usb_unanchor_urb(struct urb *urb) return; spin_lock_irqsave(&anchor->lock, flags); - if (unlikely(anchor != urb->anchor)) { - /* we've lost the race to another thread */ - spin_unlock_irqrestore(&anchor->lock, flags); - return; - } - urb->anchor = NULL; - list_del(&urb->anchor_list); + /* + * At this point, we could be competing with another thread which + * has the same intention. To protect the urb from being unanchored + * twice, only the winner of the race gets the job. + */ + if (likely(anchor == urb->anchor)) + __usb_unanchor_urb(urb, anchor); spin_unlock_irqrestore(&anchor->lock, flags); - usb_put_urb(urb); - if (list_empty(&anchor->urb_list)) - wake_up(&anchor->wait); } EXPORT_SYMBOL_GPL(usb_unanchor_urb); @@ -749,20 +756,11 @@ EXPORT_SYMBOL_GPL(usb_unpoison_anchored_urbs); void usb_unlink_anchored_urbs(struct usb_anchor *anchor) { struct urb *victim; - unsigned long flags; - spin_lock_irqsave(&anchor->lock, flags); - while (!list_empty(&anchor->urb_list)) { - victim = list_entry(anchor->urb_list.prev, struct urb, - anchor_list); - usb_get_urb(victim); - spin_unlock_irqrestore(&anchor->lock, flags); - /* this will unanchor the URB */ + while ((victim = usb_get_from_anchor(anchor)) != NULL) { usb_unlink_urb(victim); usb_put_urb(victim); - spin_lock_irqsave(&anchor->lock, flags); } - spin_unlock_irqrestore(&anchor->lock, flags); } EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs); @@ -799,12 +797,11 @@ struct urb *usb_get_from_anchor(struct usb_anchor *anchor) victim = list_entry(anchor->urb_list.next, struct urb, anchor_list); usb_get_urb(victim); - spin_unlock_irqrestore(&anchor->lock, flags); - usb_unanchor_urb(victim); + __usb_unanchor_urb(victim, anchor); } else { - spin_unlock_irqrestore(&anchor->lock, flags); victim = NULL; } + spin_unlock_irqrestore(&anchor->lock, flags); return victim; } @@ -826,12 +823,7 @@ void usb_scuttle_anchored_urbs(struct usb_anchor *anchor) while (!list_empty(&anchor->urb_list)) { victim = list_entry(anchor->urb_list.prev, struct urb, anchor_list); - usb_get_urb(victim); - spin_unlock_irqrestore(&anchor->lock, flags); - /* this may free the URB */ - usb_unanchor_urb(victim); - usb_put_urb(victim); - spin_lock_irqsave(&anchor->lock, flags); + __usb_unanchor_urb(victim, anchor); } spin_unlock_irqrestore(&anchor->lock, flags); } -- cgit v1.2.3 From 4a561f2ed8e6e5c428bae18af3f48045211add08 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Aug 2010 15:45:57 +0200 Subject: USB: serial: fix stalled writes commit b58af4066d240b18b43f202e07b9ec7461d90b17 upstream. As David VomLehn points out, it was possible to receive an interrupt before clearing the free-urb flag which could lead to the urb being incorrectly marked as busy. For the same reason, move tx_bytes accounting so that it will never be negative. Note that the free-flags set and clear operations do not need any additional locking as they are manipulated while USB_SERIAL_WRITE_BUSY is set. Reported-by: David VomLehn Tested-by: David VomLehn Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index a817ced82835..ca92f67747cc 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -208,18 +208,23 @@ retry: urb->transfer_buffer_length = count; usb_serial_debug_data(debug, &port->dev, __func__, count, urb->transfer_buffer); + spin_lock_irqsave(&port->lock, flags); + port->tx_bytes += count; + spin_unlock_irqrestore(&port->lock, flags); + + clear_bit(i, &port->write_urbs_free); result = usb_submit_urb(urb, GFP_ATOMIC); if (result) { dev_err(&port->dev, "%s - error submitting urb: %d\n", __func__, result); + set_bit(i, &port->write_urbs_free); + spin_lock_irqsave(&port->lock, flags); + port->tx_bytes -= count; + spin_unlock_irqrestore(&port->lock, flags); + clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); return result; } - clear_bit(i, &port->write_urbs_free); - - spin_lock_irqsave(&port->lock, flags); - port->tx_bytes += count; - spin_unlock_irqrestore(&port->lock, flags); /* Try sending off another urb, unless in irq context (in which case * there will be no free urb). */ -- cgit v1.2.3 From b8253929a210627b924a8a33135042cd973a48ed Mon Sep 17 00:00:00 2001 From: Cyril Lacoux Date: Wed, 14 Jul 2010 10:29:27 +0400 Subject: Bluetooth: Added support for controller shipped with iMac i5 commit 0a79f67445de50ca0a8dc1d34f3cc406d89c28b2 upstream. Device class is ff(vend.) instead of e0(wlcon). Output from command `usb-devices`: T: Bus=01 Lev=03 Prnt=03 Port=00 Cnt=01 Dev#= 6 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=05ac ProdID=8215 Rev=01.82 S: Manufacturer=Apple Inc. S: Product=Bluetooth USB Host Controller S: SerialNumber=7C6D62936607 C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=0mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=00 Driver=(none) Signed-off-by: Cyril Lacoux Signed-off-by: Marcel Holtmann Signed-off-by: Greg Kroah-Hartman --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 5d9cc53bd643..6fcb97124be8 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -59,6 +59,9 @@ static struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, + /* Apple iMac11,1 */ + { USB_DEVICE(0x05ac, 0x8215) }, + /* AVM BlueFRITZ! USB v2.0 */ { USB_DEVICE(0x057c, 0x3800) }, -- cgit v1.2.3 From 1dc89aec877583e3e42421be77b063724a4bbb07 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 9 Jul 2010 15:12:27 +0200 Subject: sched: Revert nohz_ratelimit() for now commit 396e894d289d69bacf5acd983c97cd6e21a14c08 upstream. Norbert reported that nohz_ratelimit() causes his laptop to burn about 4W (40%) extra. For now back out the change and see if we can adjust the power management code to make better decisions. Reported-by: Norbert Preining Signed-off-by: Peter Zijlstra Acked-by: Mike Galbraith Cc: Arjan van de Ven LKML-Reference: Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- include/linux/sched.h | 6 ------ kernel/sched.c | 10 ---------- kernel/time/tick-sched.c | 2 +- 3 files changed, 1 insertion(+), 17 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 0478888c6899..5ee397ee3bca 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -274,17 +274,11 @@ extern cpumask_var_t nohz_cpu_mask; #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ) extern int select_nohz_load_balancer(int cpu); extern int get_nohz_load_balancer(void); -extern int nohz_ratelimit(int cpu); #else static inline int select_nohz_load_balancer(int cpu) { return 0; } - -static inline int nohz_ratelimit(int cpu) -{ - return 0; -} #endif /* diff --git a/kernel/sched.c b/kernel/sched.c index f52a8801b7a2..63b4a14682fa 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1232,16 +1232,6 @@ void wake_up_idle_cpu(int cpu) smp_send_reschedule(cpu); } -int nohz_ratelimit(int cpu) -{ - struct rq *rq = cpu_rq(cpu); - u64 diff = rq->clock - rq->nohz_stamp; - - rq->nohz_stamp = rq->clock; - - return diff < (NSEC_PER_SEC / HZ) >> 1; -} - #endif /* CONFIG_NO_HZ */ static u64 sched_avg_period(void) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 813993b5fb61..f898af608171 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -325,7 +325,7 @@ void tick_nohz_stop_sched_tick(int inidle) } while (read_seqretry(&xtime_lock, seq)); if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) || - arch_needs_cpu(cpu) || nohz_ratelimit(cpu)) { + arch_needs_cpu(cpu)) { next_jiffies = last_jiffies + 1; delta_jiffies = 1; } else { -- cgit v1.2.3 From 01806c2cc09e580a312c9812d4c88e7ed9dfffb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20B=C3=A9nard?= Date: Thu, 10 Jun 2010 16:03:04 +0200 Subject: mtd: mxc_nand: fix unbalanced enable for IRQ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 6a8cfcfb0de881735df4031eb5cc99be3d0971e9 upstream. * preset should be done before sending the reset command * without this, I get the following error on an i.MX35 : [ 0.900000] ------------[ cut here ]------------ [ 0.900000] WARNING: at kernel/irq/manage.c:290 __enable_irq+0x4c/0x88() [ 0.900000] Unbalanced enable for IRQ 33 [ 0.900000] Modules linked in: [ 0.900000] [] (unwind_backtrace+0x0/0xf0) from [] (dump_stack+0x18/0x1c) [ 0.900000] [] (dump_stack+0x18/0x1c) from [] (warn_slowpath_common+0x54/0x6c) [ 0.900000] [] (warn_slowpath_common+0x54/0x6c) from [] (warn_slowpath_fmt+0x38/0x40) [ 0.900000] [] (warn_slowpath_fmt+0x38/0x40) from [] (__enable_irq+0x4c/0x88) [ 0.900000] [] (__enable_irq+0x4c/0x88) from [] (enable_irq+0x54/0x98) [ 0.900000] [] (enable_irq+0x54/0x98) from [] (wait_op_done+0x40/0x134) [ 0.900000] [] (wait_op_done+0x40/0x134) from [] (send_cmd+0x30/0x38) [ 0.900000] [] (send_cmd+0x30/0x38) from [] (mxc_nand_command+0x26c/0x328) [ 0.900000] [] (mxc_nand_command+0x26c/0x328) from [] (nand_scan_ident+0x188/0x6c0) [ 0.900000] [] (nand_scan_ident+0x188/0x6c0) from [] (mxcnd_probe+0x2b8/0x3d0) [ 0.900000] [] (mxcnd_probe+0x2b8/0x3d0) from [] (platform_drv_probe+0x20/0x24) [ 0.900000] [] (platform_drv_probe+0x20/0x24) from [] (driver_probe_device+0xb0/0x164) [ 0.900000] [] (driver_probe_device+0xb0/0x164) from [] (__driver_attach+0x68/0x8c) [ 0.900000] [] (__driver_attach+0x68/0x8c) from [] (bus_for_each_dev+0x50/0x84) [ 0.900000] [] (bus_for_each_dev+0x50/0x84) from [] (driver_attach+0x20/0x28) [ 0.900000] [] (driver_attach+0x20/0x28) from [] (bus_add_driver+0x144/0x2dc) [ 0.900000] [] (bus_add_driver+0x144/0x2dc) from [] (driver_register+0xb0/0x13c) [ 0.900000] [] (driver_register+0xb0/0x13c) from [] (platform_driver_register+0x4c/0x60) [ 0.900000] [] (platform_driver_register+0x4c/0x60) from [] (platform_driver_probe+0x20/0xa0) [ 0.900000] [] (platform_driver_probe+0x20/0xa0) from [] (mxc_nd_init+0x18/0x24) [ 0.900000] [] (mxc_nd_init+0x18/0x24) from [] (do_one_initcall+0x64/0x1bc) [ 0.900000] [] (do_one_initcall+0x64/0x1bc) from [] (kernel_init+0xe8/0x1ac) [ 0.900000] [] (kernel_init+0xe8/0x1ac) from [] (kernel_thread_exit+0x0/0x8) [ 0.900000] ---[ end trace 8bf72ac6ba089a19 ]--- [ 1.140000] NAND device: Manufacturer ID: 0x2c, Chip ID: 0xda (Micron NAND 256MiB 3,3V 8-bit) Signed-off-by: Eric Bénard Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/mxc_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 82e94389824e..88785032322a 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -604,8 +604,8 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, /* Command pre-processing step */ switch (command) { case NAND_CMD_RESET: - send_cmd(host, command, false); preset(mtd); + send_cmd(host, command, false); break; case NAND_CMD_STATUS: -- cgit v1.2.3 From a456e2bf311123a0d2fa313a7e51611ab7b0439e Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 28 Jul 2010 07:36:54 +0200 Subject: mtd: gen_nand: fix support for multiple chips commit 81cbb0b17796d81cbd92defe113cf2a7c7a21fbb upstream. This patch corrects a problem where gen_nand driver assumed there can be only one chip and ignored the pdata->chip.nr_chips value. Signed-off-by: Marek Vasut Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/plat_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index 8d467315f02b..90e143e5ad3e 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c @@ -91,7 +91,7 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) } /* Scan to find existance of the device */ - if (nand_scan(&data->mtd, 1)) { + if (nand_scan(&data->mtd, pdata->chip.nr_chips)) { err = -ENXIO; goto out; } -- cgit v1.2.3 From ba87b9af0a503058e6db99c6a4be87157dbad322 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Tue, 3 Aug 2010 00:42:17 -0700 Subject: l2tp: fix export of header file for userspace commit 4565956dc0847985c0403c9ebbf274b6a122e1e2 upstream. The header file l2tp.h should be exported to the installed include/linux/ tree for userspace programs. This patch fixes compilation errors in L2TP userspace apps which want to use the new L2TP support introduced in 2.6.35. Signed-off-by: James Chapman Signed-off-by: Andrew Morton Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/Kbuild | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 2fc8e14cc24a..9aa9bcadf869 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -276,6 +276,7 @@ ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm_para.h \ $(srctree)/include/asm-$(SRCARCH)/kvm_para.h),) unifdef-y += kvm_para.h endif +unifdef-y += l2tp.h unifdef-y += llc.h unifdef-y += loop.h unifdef-y += lp.h -- cgit v1.2.3 From 60bee7a88f10d0e7f4595dbd81f53daf37833383 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 9 Aug 2010 15:57:38 -0500 Subject: jfs: don't allow os2 xattr namespace overlap with others commit aca0fa34bdaba39bfddddba8ca70dba4782e8fe6 upstream. It's currently possible to bypass xattr namespace access rules by prefixing valid xattr names with "os2.", since the os2 namespace stores extended attributes in a legacy format with no prefix. This patch adds checking to deny access to any valid namespace prefix following "os2.". Signed-off-by: Dave Kleikamp Reported-by: Sergey Vlasov Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/jfs/xattr.c | 87 +++++++++++++++++++++++++--------------------------------- 1 file changed, 38 insertions(+), 49 deletions(-) diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index fa96bbb26343..2d7f165d0f1d 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -86,46 +86,25 @@ struct ea_buffer { #define EA_MALLOC 0x0008 +static int is_known_namespace(const char *name) +{ + if (strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) && + strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) && + strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) && + strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) + return false; + + return true; +} + /* * These three routines are used to recognize on-disk extended attributes * that are in a recognized namespace. If the attribute is not recognized, * "os2." is prepended to the name */ -static inline int is_os2_xattr(struct jfs_ea *ea) +static int is_os2_xattr(struct jfs_ea *ea) { - /* - * Check for "system." - */ - if ((ea->namelen >= XATTR_SYSTEM_PREFIX_LEN) && - !strncmp(ea->name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) - return false; - /* - * Check for "user." - */ - if ((ea->namelen >= XATTR_USER_PREFIX_LEN) && - !strncmp(ea->name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) - return false; - /* - * Check for "security." - */ - if ((ea->namelen >= XATTR_SECURITY_PREFIX_LEN) && - !strncmp(ea->name, XATTR_SECURITY_PREFIX, - XATTR_SECURITY_PREFIX_LEN)) - return false; - /* - * Check for "trusted." - */ - if ((ea->namelen >= XATTR_TRUSTED_PREFIX_LEN) && - !strncmp(ea->name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) - return false; - /* - * Add any other valid namespace prefixes here - */ - - /* - * We assume it's OS/2's flat namespace - */ - return true; + return !is_known_namespace(ea->name); } static inline int name_size(struct jfs_ea *ea) @@ -764,13 +743,23 @@ static int can_set_xattr(struct inode *inode, const char *name, if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) return can_set_system_xattr(inode, name, value, value_len); + if (!strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)) { + /* + * This makes sure that we aren't trying to set an + * attribute in a different namespace by prefixing it + * with "os2." + */ + if (is_known_namespace(name + XATTR_OS2_PREFIX_LEN)) + return -EOPNOTSUPP; + return 0; + } + /* * Don't allow setting an attribute in an unknown namespace. */ if (strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) && strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) && - strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) && - strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)) + strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) return -EOPNOTSUPP; return 0; @@ -952,19 +941,8 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data, int xattr_size; ssize_t size; int namelen = strlen(name); - char *os2name = NULL; char *value; - if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { - os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1, - GFP_KERNEL); - if (!os2name) - return -ENOMEM; - strcpy(os2name, name + XATTR_OS2_PREFIX_LEN); - name = os2name; - namelen -= XATTR_OS2_PREFIX_LEN; - } - down_read(&JFS_IP(inode)->xattr_sem); xattr_size = ea_get(inode, &ea_buf, 0); @@ -1002,8 +980,6 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data, out: up_read(&JFS_IP(inode)->xattr_sem); - kfree(os2name); - return size; } @@ -1012,6 +988,19 @@ ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data, { int err; + if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { + /* + * skip past "os2." prefix + */ + name += XATTR_OS2_PREFIX_LEN; + /* + * Don't allow retrieving properly prefixed attributes + * by prepending them with "os2." + */ + if (is_known_namespace(name)) + return -EOPNOTSUPP; + } + err = __jfs_getxattr(dentry->d_inode, name, data, buf_size); return err; -- cgit v1.2.3 From 488a52f0cbf44b44ebec2f52e172e8c83adad41b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 31 May 2010 00:28:35 -0700 Subject: net: Fix NETDEV_NOTIFY_PEERS to not conflict with NETDEV_BONDING_DESLAVE. commit 38117d1495e587fbb10d6e55733139a27893cef5 upstream. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/notifier.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/notifier.h b/include/linux/notifier.h index 22c2abb61974..b2f1a4d83550 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h @@ -210,7 +210,7 @@ static inline int notifier_to_errno(int ret) #define NETDEV_POST_INIT 0x0010 #define NETDEV_UNREGISTER_BATCH 0x0011 #define NETDEV_BONDING_DESLAVE 0x0012 -#define NETDEV_NOTIFY_PEERS 0x0012 +#define NETDEV_NOTIFY_PEERS 0x0013 #define SYS_DOWN 0x0001 /* Notify of system down */ #define SYS_RESTART SYS_DOWN -- cgit v1.2.3 From 88154b0e0ce03c31f24f76e7bde69bbdd6998018 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 29 Jul 2010 11:16:32 +0100 Subject: irq: Add new IRQ flag IRQF_NO_SUSPEND commit 685fd0b4ea3f0f1d5385610b0d5b57775a8d5842 upstream. A small number of users of IRQF_TIMER are using it for the implied no suspend behaviour on interrupts which are not timer interrupts. Therefore add a new IRQF_NO_SUSPEND flag, rename IRQF_TIMER to __IRQF_TIMER and redefine IRQF_TIMER in terms of these new flags. Signed-off-by: Ian Campbell Cc: Jeremy Fitzhardinge Cc: Dmitry Torokhov Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Grant Likely Cc: xen-devel@lists.xensource.com Cc: linux-input@vger.kernel.org Cc: linuxppc-dev@ozlabs.org Cc: devicetree-discuss@lists.ozlabs.org LKML-Reference: <1280398595-29708-1-git-send-email-ian.campbell@citrix.com> Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- include/linux/interrupt.h | 7 ++++++- kernel/irq/manage.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index c2331138ca1b..a0384a4d1e6f 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -53,16 +53,21 @@ * IRQF_ONESHOT - Interrupt is not reenabled after the hardirq handler finished. * Used by threaded interrupts which need to keep the * irq line disabled until the threaded handler has been run. + * IRQF_NO_SUSPEND - Do not disable this IRQ during suspend + * */ #define IRQF_DISABLED 0x00000020 #define IRQF_SAMPLE_RANDOM 0x00000040 #define IRQF_SHARED 0x00000080 #define IRQF_PROBE_SHARED 0x00000100 -#define IRQF_TIMER 0x00000200 +#define __IRQF_TIMER 0x00000200 #define IRQF_PERCPU 0x00000400 #define IRQF_NOBALANCING 0x00000800 #define IRQF_IRQPOLL 0x00001000 #define IRQF_ONESHOT 0x00002000 +#define IRQF_NO_SUSPEND 0x00004000 + +#define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND) /* * Bits used by threaded handlers: diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index e1497481fe8a..c3003e9d91a3 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -216,7 +216,7 @@ static inline int setup_affinity(unsigned int irq, struct irq_desc *desc) void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend) { if (suspend) { - if (!desc->action || (desc->action->flags & IRQF_TIMER)) + if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND)) return; desc->status |= IRQ_SUSPENDED; } -- cgit v1.2.3 From 925a7e4a56ab113a1703caf76be0311f70d53b89 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 29 Jul 2010 11:16:35 +0100 Subject: xen: Do not suspend IPI IRQs. commit 4877c737283813bdb4bebfa3168c1585f6e3a8ca upstream. In general the semantics of IPIs are that they are are expected to continue functioning after dpm_suspend_noirq(). Specifically I have seen a deadlock between the callfunc IPI and the stop machine used by xen's do_suspend() routine. If one CPU has already called dpm_suspend_noirq() then there is a window where it can be sent a callfunc IPI before all the other CPUs have entered stop_cpu(). If this happens then the first CPU ends up spinning in stop_cpu() waiting for the other to rendezvous in state STOPMACHINE_PREPARE while the other is spinning in csd_lock_wait(). Signed-off-by: Ian Campbell Cc: Jeremy Fitzhardinge Cc: xen-devel@lists.xensource.com LKML-Reference: <1280398595-29708-4-git-send-email-ian.campbell@citrix.com> Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- drivers/xen/events.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index db8f506817f0..28f133ae76ad 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -536,6 +536,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi, if (irq < 0) return irq; + irqflags |= IRQF_NO_SUSPEND; retval = request_irq(irq, handler, irqflags, devname, dev_id); if (retval != 0) { unbind_from_irq(irq); -- cgit v1.2.3 From c1e592f0ba284b88ade340fe2c5963bfdc621f28 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Thu, 3 Jun 2010 20:53:43 +1000 Subject: crypto: testmgr - add an option to disable cryptoalgos' self-tests commit 0b767f96164b2b27488e3daa722ff16e89d49314 upstream. By default, CONFIG_CRYPTO_MANAGER_TESTS will be enabled and thus self-tests will still run, but it is now possible to disable them to gain some time during bootup. Signed-off-by: Alexander Shishkin Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- crypto/Kconfig | 8 ++++++++ crypto/algboss.c | 4 ++++ crypto/testmgr.c | 14 ++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/crypto/Kconfig b/crypto/Kconfig index 9d9434f08c92..df332c140f95 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -96,6 +96,14 @@ config CRYPTO_MANAGER2 select CRYPTO_BLKCIPHER2 select CRYPTO_PCOMP +config CRYPTO_MANAGER_TESTS + bool "Run algolithms' self-tests" + default y + depends on CRYPTO_MANAGER2 + help + Run cryptomanager's tests for the new crypto algorithms being + registered. + config CRYPTO_GF128MUL tristate "GF(2^128) multiplication functions (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/crypto/algboss.c b/crypto/algboss.c index c3c196b5823a..40bd391f34d9 100644 --- a/crypto/algboss.c +++ b/crypto/algboss.c @@ -206,6 +206,7 @@ err: return NOTIFY_OK; } +#ifdef CONFIG_CRYPTO_MANAGER_TESTS static int cryptomgr_test(void *data) { struct crypto_test_param *param = data; @@ -266,6 +267,7 @@ err_put_module: err: return NOTIFY_OK; } +#endif /* CONFIG_CRYPTO_MANAGER_TESTS */ static int cryptomgr_notify(struct notifier_block *this, unsigned long msg, void *data) @@ -273,8 +275,10 @@ static int cryptomgr_notify(struct notifier_block *this, unsigned long msg, switch (msg) { case CRYPTO_MSG_ALG_REQUEST: return cryptomgr_schedule_probe(data); +#ifdef CONFIG_CRYPTO_MANAGER_TESTS case CRYPTO_MSG_ALG_REGISTER: return cryptomgr_schedule_test(data); +#endif } return NOTIFY_DONE; diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 5c8aaa0cb0b9..abd980c729eb 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -22,6 +22,17 @@ #include #include "internal.h" + +#ifndef CONFIG_CRYPTO_MANAGER_TESTS + +/* a perfect nop */ +int alg_test(const char *driver, const char *alg, u32 type, u32 mask) +{ + return 0; +} + +#else + #include "testmgr.h" /* @@ -2530,4 +2541,7 @@ notest: non_fips_alg: return -EINVAL; } + +#endif /* CONFIG_CRYPTO_MANAGER_TESTS */ + EXPORT_SYMBOL_GPL(alg_test); -- cgit v1.2.3 From 96fbd3f232d1c0b0c174b5804dce35f16c7eae63 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Sun, 1 Aug 2010 17:33:29 -0400 Subject: ext4: fix freeze deadlock under IO commit 437f88cc031ffe7f37f3e705367f4fe1f4be8b0f upstream. Commit 6b0310fbf087ad6 caused a regression resulting in deadlocks when freezing a filesystem which had active IO; the vfs_check_frozen level (SB_FREEZE_WRITE) did not let the freeze-related IO syncing through. Duh. Changing the test to FREEZE_TRANS should let the normal freeze syncing get through the fs, but still block any transactions from starting once the fs is completely frozen. I tested this by running fsstress in the background while periodically snapshotting the fs and running fsck on the result. I ran into occasional deadlocks, but different ones. I think this is a fine fix for the problem at hand, and the other deadlocky things will need more investigation. Reported-by: Phillip Susi Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/super.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 4e8983a9811b..a45ced96b042 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -241,7 +241,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) if (sb->s_flags & MS_RDONLY) return ERR_PTR(-EROFS); - vfs_check_frozen(sb, SB_FREEZE_WRITE); + vfs_check_frozen(sb, SB_FREEZE_TRANS); /* Special case here: if the journal has aborted behind our * backs (eg. EIO in the commit thread), then we still need to * take the FS itself readonly cleanly. */ @@ -3491,7 +3491,7 @@ int ext4_force_commit(struct super_block *sb) journal = EXT4_SB(sb)->s_journal; if (journal) { - vfs_check_frozen(sb, SB_FREEZE_WRITE); + vfs_check_frozen(sb, SB_FREEZE_TRANS); ret = ext4_journal_force_commit(journal); } -- cgit v1.2.3 From 52423b90e1f5b1bdbbcc6e32f4d37ada29b790c4 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 12 Aug 2010 17:54:33 -0700 Subject: mm: keep a guard page below a grow-down stack segment commit 320b2b8de12698082609ebbc1a17165727f4c893 upstream. This is a rather minimally invasive patch to solve the problem of the user stack growing into a memory mapped area below it. Whenever we fill the first page of the stack segment, expand the segment down by one page. Now, admittedly some odd application might _want_ the stack to grow down into the preceding memory mapping, and so we may at some point need to make this a process tunable (some people might also want to have more than a single page of guarding), but let's try the minimal approach first. Tested with trivial application that maps a single page just below the stack, and then starts recursing. Without this, we will get a SIGSEGV _after_ the stack has smashed the mapping. With this patch, we'll get a nice SIGBUS just as the stack touches the page just above the mapping. Requested-by: Keith Packard Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/memory.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/mm/memory.c b/mm/memory.c index bde42c6d3633..c43447382fec 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2759,6 +2759,26 @@ out_release: return ret; } +/* + * This is like a special single-page "expand_downwards()", + * except we must first make sure that 'address-PAGE_SIZE' + * doesn't hit another vma. + * + * The "find_vma()" will do the right thing even if we wrap + */ +static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address) +{ + address &= PAGE_MASK; + if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) { + address -= PAGE_SIZE; + if (find_vma(vma->vm_mm, address) != vma) + return -ENOMEM; + + expand_stack(vma, address); + } + return 0; +} + /* * We enter with non-exclusive mmap_sem (to exclude vma changes, * but allow concurrent faults), and pte mapped but not yet locked. @@ -2772,6 +2792,9 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, spinlock_t *ptl; pte_t entry; + if (check_stack_guard_page(vma, address) < 0) + return VM_FAULT_SIGBUS; + if (!(flags & FAULT_FLAG_WRITE)) { entry = pte_mkspecial(pfn_pte(my_zero_pfn(address), vma->vm_page_prot)); -- cgit v1.2.3 From 3aba3fa070fc0f38de2d41252aee9ff17d2de984 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 13 Aug 2010 09:24:04 -0700 Subject: mm: fix missing page table unmap for stack guard page failure case commit 5528f9132cf65d4d892bcbc5684c61e7822b21e9 upstream. .. which didn't show up in my tests because it's a no-op on x86-64 and most other architectures. But we enter the function with the last-level page table mapped, and should unmap it at exit. Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/memory.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mm/memory.c b/mm/memory.c index c43447382fec..aaaedbd2080c 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2792,8 +2792,10 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, spinlock_t *ptl; pte_t entry; - if (check_stack_guard_page(vma, address) < 0) + if (check_stack_guard_page(vma, address) < 0) { + pte_unmap(page_table); return VM_FAULT_SIGBUS; + } if (!(flags & FAULT_FLAG_WRITE)) { entry = pte_mkspecial(pfn_pte(my_zero_pfn(address), -- cgit v1.2.3 From 76e3b8d9764ca43452b272925df0b05625f98898 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 13 Aug 2010 09:49:20 -0700 Subject: x86: don't send SIGBUS for kernel page faults commit 96054569190bdec375fe824e48ca1f4e3b53dd36 upstream. It's wrong for several reasons, but the most direct one is that the fault may be for the stack accesses to set up a previous SIGBUS. When we have a kernel exception, the kernel exception handler does all the fixups, not some user-level signal handler. Even apart from the nested SIGBUS issue, it's also wrong to give out kernel fault addresses in the signal handler info block, or to send a SIGBUS when a system call already returns EFAULT. Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/fault.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index f62777940dfb..4c4508e8a204 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -802,8 +802,10 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, up_read(&mm->mmap_sem); /* Kernel mode? Handle exceptions or die: */ - if (!(error_code & PF_USER)) + if (!(error_code & PF_USER)) { no_context(regs, error_code, address); + return; + } /* User-space => ok to do another page fault: */ if (is_prefetch(regs, error_code, address)) -- cgit v1.2.3 From f6b0f3c69141a21f12cb2f678b0cdaa2be8076a7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 13 Aug 2010 13:44:56 -0700 Subject: Linux 2.6.35.2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0b9c76386b96..3cf23970d5f3 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 35 -EXTRAVERSION = .1 +EXTRAVERSION = .2 NAME = Sheep on Meth # *DOCUMENTATION* -- cgit v1.2.3 From 16af977da0867b1f9fdc98fb61f10ef85a7b60e7 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 14 Aug 2010 11:44:56 -0700 Subject: mm: fix page table unmap for stack guard page properly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 11ac552477e32835cb6970bf0a70c210807f5673 upstream. We do in fact need to unmap the page table _before_ doing the whole stack guard page logic, because if it is needed (mainly 32-bit x86 with PAE and CONFIG_HIGHPTE, but other architectures may use it too) then it will do a kmap_atomic/kunmap_atomic. And those kmaps will create an atomic region that we cannot do allocations in. However, the whole stack expand code will need to do anon_vma_prepare() and vma_lock_anon_vma() and they cannot do that in an atomic region. Now, a better model might actually be to do the anon_vma_prepare() when _creating_ a VM_GROWSDOWN segment, and not have to worry about any of this at page fault time. But in the meantime, this is the straightforward fix for the issue. See https://bugzilla.kernel.org/show_bug.cgi?id=16588 for details. Reported-by: Wylda Reported-by: Sedat Dilek Reported-by: Mike Pagano Reported-by: François Valenduc Tested-by: Ed Tomlinson Cc: Pekka Enberg Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/memory.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index aaaedbd2080c..307bf77fc441 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2792,24 +2792,23 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, spinlock_t *ptl; pte_t entry; - if (check_stack_guard_page(vma, address) < 0) { - pte_unmap(page_table); + pte_unmap(page_table); + + /* Check if we need to add a guard page to the stack */ + if (check_stack_guard_page(vma, address) < 0) return VM_FAULT_SIGBUS; - } + /* Use the zero-page for reads */ if (!(flags & FAULT_FLAG_WRITE)) { entry = pte_mkspecial(pfn_pte(my_zero_pfn(address), vma->vm_page_prot)); - ptl = pte_lockptr(mm, pmd); - spin_lock(ptl); + page_table = pte_offset_map_lock(mm, pmd, address, &ptl); if (!pte_none(*page_table)) goto unlock; goto setpte; } /* Allocate our own private page. */ - pte_unmap(page_table); - if (unlikely(anon_vma_prepare(vma))) goto oom; page = alloc_zeroed_user_highpage_movable(vma, address); -- cgit v1.2.3 From 44768880969473a1edae3ba4ea10d1850cf2ddb5 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 15 Aug 2010 11:35:52 -0700 Subject: mm: fix up some user-visible effects of the stack guard page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit d7824370e26325c881b665350ce64fb0a4fde24a upstream. This commit makes the stack guard page somewhat less visible to user space. It does this by: - not showing the guard page in /proc//maps It looks like lvm-tools will actually read /proc/self/maps to figure out where all its mappings are, and effectively do a specialized "mlockall()" in user space. By not showing the guard page as part of the mapping (by just adding PAGE_SIZE to the start for grows-up pages), lvm-tools ends up not being aware of it. - by also teaching the _real_ mlock() functionality not to try to lock the guard page. That would just expand the mapping down to create a new guard page, so there really is no point in trying to lock it in place. It would perhaps be nice to show the guard page specially in /proc//maps (or at least mark grow-down segments some way), but let's not open ourselves up to more breakage by user space from programs that depends on the exact deails of the 'maps' file. Special thanks to Henrique de Moraes Holschuh for diving into lvm-tools source code to see what was going on with the whole new warning. Reported-and-tested-by: François Valenduc Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/proc/task_mmu.c | 8 +++++++- mm/mlock.c | 8 ++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index aea1d3f1ffb5..439fc1f1c1c4 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -210,6 +210,7 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) int flags = vma->vm_flags; unsigned long ino = 0; unsigned long long pgoff = 0; + unsigned long start; dev_t dev = 0; int len; @@ -220,8 +221,13 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT; } + /* We don't show the stack guard page in /proc/maps */ + start = vma->vm_start; + if (vma->vm_flags & VM_GROWSDOWN) + start += PAGE_SIZE; + seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", - vma->vm_start, + start, vma->vm_end, flags & VM_READ ? 'r' : '-', flags & VM_WRITE ? 'w' : '-', diff --git a/mm/mlock.c b/mm/mlock.c index 3f82720e0515..49e5e4cb8232 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -167,6 +167,14 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma, if (vma->vm_flags & VM_WRITE) gup_flags |= FOLL_WRITE; + /* We don't try to access the guard page of a stack vma */ + if (vma->vm_flags & VM_GROWSDOWN) { + if (start == vma->vm_start) { + start += PAGE_SIZE; + nr_pages--; + } + } + while (nr_pages > 0) { int i; -- cgit v1.2.3 From 19b94a73cb37fa30ecd49858a09218cde908aee6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Aug 2010 13:06:12 -0700 Subject: vmware: fix build error in vmware.c This fixes a build error reported in vmware.c due to commit 9f242dc10e0c3c1eb32d8c83c18650a35fd7f80d Reported-by: Sven Joachim Cc: Alok Kataria Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/vmware.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index 227b0448960d..ce9c6c28de77 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include -- cgit v1.2.3 From 6d23f5084c975be637f7d748db82116bf84d3872 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 20 Aug 2010 11:55:55 -0700 Subject: Linux 2.6.35.3 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3cf23970d5f3..554683d03919 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 35 -EXTRAVERSION = .2 +EXTRAVERSION = .3 NAME = Sheep on Meth # *DOCUMENTATION* -- cgit v1.2.3 From da6827e8b0e9b7c43b25396017a5198040cbc2f6 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Wed, 11 Aug 2010 14:17:52 -0700 Subject: memstick: init sysfs attributes commit 21fd0495ea61d53e0ebe575330e343ce4e6d2a61 upstream. Otherwise lockdep complains. Signed-off-by: Maxim Levitsky Cc: Alex Dubov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/memstick/core/mspro_block.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 8327e248520a..369313fa359a 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -1040,6 +1040,7 @@ static int mspro_block_read_attributes(struct memstick_dev *card) snprintf(s_attr->name, sizeof(s_attr->name), "attr_x%02x", attr->entries[cnt].id); + sysfs_attr_init(&s_attr->dev_attr.attr); s_attr->dev_attr.attr.name = s_attr->name; s_attr->dev_attr.attr.mode = S_IRUGO; s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id); -- cgit v1.2.3 From e9eee0b456fee111f5d6def1e562dd17e39f2b65 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Wed, 11 Aug 2010 14:17:52 -0700 Subject: memstick: fix hangs on unexpected device removal in mspro_blk commit d862b13bc8cbab9692fbe0ef44c40d0488b81af1 upstream. mspro_block_remove() is called from detect thread that first calls the mspro_block_stop(), which stops the request queue. If we call del_gendisk() with the queue stopped we get a deadlock. Signed-off-by: Maxim Levitsky Cc: Alex Dubov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/memstick/core/mspro_block.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 369313fa359a..300ec1595f1f 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -1331,13 +1331,14 @@ static void mspro_block_remove(struct memstick_dev *card) struct mspro_block_data *msb = memstick_get_drvdata(card); unsigned long flags; - del_gendisk(msb->disk); - dev_dbg(&card->dev, "mspro block remove\n"); spin_lock_irqsave(&msb->q_lock, flags); msb->eject = 1; blk_start_queue(msb->queue); spin_unlock_irqrestore(&msb->q_lock, flags); + del_gendisk(msb->disk); + dev_dbg(&card->dev, "mspro block remove\n"); + blk_cleanup_queue(msb->queue); msb->queue = NULL; -- cgit v1.2.3 From d3ad3eb081014cb4baf2b87f394bc3ec4779ef16 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 11 Aug 2010 14:17:29 -0700 Subject: acpi: fix bogus preemption logic commit 0a7992c90828a65281c3c9cf180be3b432d277b2 upstream. The ACPI_PREEMPTION_POINT() logic was introduced in commit 8bd108d (ACPICA: add preemption point after each opcode parse). The follow up commits abe1dfab6, 138d15692, c084ca70 tried to fix the preemption logic back and forth, but nobody noticed that the usage of in_atomic_preempt_off() in that context is wrong. The check which guards the call of cond_resched() is: if (!in_atomic_preempt_off() && !irqs_disabled()) in_atomic_preempt_off() is not intended for general use as the comment above the macro definition clearly says: * Check whether we were atomic before we did preempt_disable(): * (used by the scheduler, *after* releasing the kernel lock) On a CONFIG_PREEMPT=n kernel the usage of in_atomic_preempt_off() works by accident, but with CONFIG_PREEMPT=y it's just broken. The whole purpose of the ACPI_PREEMPTION_POINT() is to reduce the latency on a CONFIG_PREEMPT=n kernel, so make ACPI_PREEMPTION_POINT() depend on CONFIG_PREEMPT=n and remove the in_atomic_preempt_off() check. Addresses https://bugzilla.kernel.org/show_bug.cgi?id=16210 [akpm@linux-foundation.org: fix build] Signed-off-by: Thomas Gleixner Cc: Len Brown Cc: Francois Valenduc Cc: Lin Ming Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/apei/erst.c | 1 + include/acpi/platform/aclinux.h | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 864dd46c346f..18645f4e83cd 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "apei-internal.h" diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index e5039a2856f8..103f08aca764 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -148,13 +148,17 @@ static inline void *acpi_os_acquire_object(acpi_cache_t * cache) #define ACPI_ALLOCATE_ZEROED(a) acpi_os_allocate_zeroed(a) #define ACPI_FREE(a) kfree(a) -/* Used within ACPICA to show where it is safe to preempt execution */ -#include +#ifndef CONFIG_PREEMPT +/* + * Used within ACPICA to show where it is safe to preempt execution + * when CONFIG_PREEMPT=n + */ #define ACPI_PREEMPTION_POINT() \ do { \ - if (!in_atomic_preempt_off() && !irqs_disabled()) \ + if (!irqs_disabled()) \ cond_resched(); \ } while (0) +#endif #endif /* __KERNEL__ */ -- cgit v1.2.3 From 1360aa27ce9d429494559a85375392729317123e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 6 Aug 2010 17:57:12 +0100 Subject: ASoC: Fix inverted mute controls for WM8580 commit 4f0ed9a51bc8ef16c2589112fdb110479e4b0df1 upstream. Signed-off-by: Mark Brown Acked-by: Liam Girdwood Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm8580.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index c3571ee5c11b..72deeabef4fe 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -269,9 +269,9 @@ SOC_DOUBLE("DAC2 Invert Switch", WM8580_DAC_CONTROL4, 2, 3, 1, 0), SOC_DOUBLE("DAC3 Invert Switch", WM8580_DAC_CONTROL4, 4, 5, 1, 0), SOC_SINGLE("DAC ZC Switch", WM8580_DAC_CONTROL5, 5, 1, 0), -SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 0), -SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 0), -SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 0), +SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 1), +SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 1), +SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 1), SOC_DOUBLE("ADC Mute Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0), SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), -- cgit v1.2.3 From f62010c99c29bf3ebe9f2d643d055445222cb03c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 16 Aug 2010 11:46:57 +0100 Subject: ASoC: Remove DSP mode support for WM8776 commit b2c1e07b81a126e5846dfc3d36f559d861df59f4 upstream. This is not supported by current hardware revisions. Signed-off-by: Mark Brown Acked-by: Liam Girdwood Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm8776.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 4e212ed62ea6..f8154e661524 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -178,13 +178,6 @@ static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_LEFT_J: iface |= 0x0001; break; - /* FIXME: CHECK A/B */ - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= 0x0007; - break; default: return -EINVAL; } -- cgit v1.2.3 From a4e5c5d32bedabd04a246892d5f4422322591191 Mon Sep 17 00:00:00 2001 From: Cliff Cai Date: Sat, 7 Aug 2010 11:16:27 -0400 Subject: ASoC: register cache should be 1 byte aligned for 1 byte long register commit ac770267a7cd85a747b6111db46f66d1515e7cd7 upstream. Signed-off-by: Cliff Cai Signed-off-by: Mike Frysinger Acked-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/soc-cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 472af38188c1..adbc68ce9050 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -340,7 +340,7 @@ static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec, static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec, unsigned int reg) { - u16 *cache = codec->reg_cache; + u8 *cache = codec->reg_cache; reg &= 0xff; if (reg >= codec->reg_cache_size) @@ -351,7 +351,7 @@ static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec, static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { - u16 *cache = codec->reg_cache; + u8 *cache = codec->reg_cache; u8 data[3]; int ret; -- cgit v1.2.3 From 4e354ad43ae9c3b9e634cdfcb8d0920cd7278afd Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Fri, 6 Aug 2010 15:48:24 +0100 Subject: regulator: Default GPIO controlled WM8994 regulators to disabled commit c4604e49c1a5832a58789a22eba7ca982933e1be upstream. This ensures that if the GPIO was not enabled prior to the driver starting the regulator API will insert the required powerup ramp delay when it enables the regulator. The gpiolib API does not provide this information. [Rewrote changelog to describe the actual change -- broonie.] Signed-off-by: Joonyoung Shim Signed-off-by: Mark Brown Signed-off-by: Liam Girdwood Signed-off-by: Greg Kroah-Hartman --- drivers/regulator/wm8994-regulator.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index 5a1dc8a24d35..03713bc66e4a 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -219,8 +219,6 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) ldo->wm8994 = wm8994; - ldo->is_enabled = true; - if (pdata->ldo[id].enable && gpio_is_valid(pdata->ldo[id].enable)) { ldo->enable = pdata->ldo[id].enable; @@ -237,7 +235,8 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) ret); goto err_gpio; } - } + } else + ldo->is_enabled = true; ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &pdev->dev, pdata->ldo[id].init_data, ldo); -- cgit v1.2.3 From 6c877dfbe9b81983e254bdd6aa8854fb2a288604 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 16 Aug 2010 08:08:48 +0200 Subject: ALSA: riptide - Fix detection / load of firmware files commit a5ba6beb839cfa288960c92cd2668a2601c24dda upstream. The detection and loading of firmeware on riptide driver has been broken due to rewrite of some codes, checking the presense wrongly. This patch fixes the logic again. Reference: kernel bug 16596 https://bugzilla.kernel.org/show_bug.cgi?id=16596 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/riptide/riptide.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index ad4462677615..c737287bcae9 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -1224,15 +1224,14 @@ static int try_to_load_firmware(struct cmdif *cif, struct snd_riptide *chip) firmware.firmware.ASIC, firmware.firmware.CODEC, firmware.firmware.AUXDSP, firmware.firmware.PROG); + if (!chip) + return 1; + for (i = 0; i < FIRMWARE_VERSIONS; i++) { if (!memcmp(&firmware_versions[i], &firmware, sizeof(firmware))) - break; - } - if (i >= FIRMWARE_VERSIONS) - return 0; /* no match */ + return 1; /* OK */ - if (!chip) - return 1; /* OK */ + } snd_printdd("Writing Firmware\n"); if (!chip->fw_entry) { -- cgit v1.2.3 From 2f10b29273e6a54a870cd9c6cbaf7bd5326cb547 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 18 Aug 2010 14:08:17 +0200 Subject: ALSA: emu10k1 - delay the PCM interrupts (add pcm_irq_delay parameter) commit 56385a12d9bb9e173751f74b6c430742018cafc0 upstream. With some hardware combinations, the PCM interrupts are acknowledged before the period boundary from the emu10k1 chip. The midlevel PCM code gets confused and the playback stream is interrupted. It seems that the interrupt processing shift by 2 samples is enough to fix this issue. This default value does not harm other, non-affected hardware. More information: Kernel bugzilla bug#16300 [A copmile warning fixed by tiwai] Signed-off-by: Jaroslav Kysela Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- include/sound/emu10k1.h | 1 + sound/core/pcm_native.c | 4 ++++ sound/pci/emu10k1/emu10k1.c | 4 ++++ sound/pci/emu10k1/emupcm.c | 30 ++++++++++++++++++++++++++---- sound/pci/emu10k1/memory.c | 4 +++- 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index 6a664c3f7c1e..7dc97d12253c 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h @@ -1707,6 +1707,7 @@ struct snd_emu10k1 { unsigned int card_type; /* EMU10K1_CARD_* */ unsigned int ecard_ctrl; /* ecard control bits */ unsigned long dma_mask; /* PCI DMA mask */ + unsigned int delay_pcm_irq; /* in samples */ int max_cache_pages; /* max memory size / PAGE_SIZE */ struct snd_dma_buffer silent_page; /* silent page */ struct snd_dma_buffer ptb_pages; /* page table pages */ diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 303ac04ff6e4..1990918cd0da 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -981,6 +981,10 @@ static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push) { if (substream->runtime->trigger_master != substream) return 0; + /* some drivers might use hw_ptr to recover from the pause - + update the hw_ptr now */ + if (push) + snd_pcm_update_hw_ptr(substream); /* The jiffies check in snd_pcm_update_hw_ptr*() is done by * a delta betwen the current jiffies, this gives a large enough * delta, effectively to skip the check once. diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 4203782d7cb7..aff8387c45cf 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -52,6 +52,7 @@ static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64}; static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128}; static int enable_ir[SNDRV_CARDS]; static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */ +static uint delay_pcm_irq[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard."); @@ -73,6 +74,8 @@ module_param_array(enable_ir, bool, NULL, 0444); MODULE_PARM_DESC(enable_ir, "Enable IR."); module_param_array(subsystem, uint, NULL, 0444); MODULE_PARM_DESC(subsystem, "Force card subsystem model."); +module_param_array(delay_pcm_irq, uint, NULL, 0444); +MODULE_PARM_DESC(delay_pcm_irq, "Delay PCM interrupt by specified number of samples (default 0)."); /* * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 */ @@ -127,6 +130,7 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, &emu)) < 0) goto error; card->private_data = emu; + emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f; if ((err = snd_emu10k1_pcm(emu, 0, NULL)) < 0) goto error; if ((err = snd_emu10k1_pcm_mic(emu, 1, NULL)) < 0) diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 55b83ef73c63..622bace148e3 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -332,7 +332,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, evoice->epcm->ccca_start_addr = start_addr + ccis; if (extra) { start_addr += ccis; - end_addr += ccis; + end_addr += ccis + emu->delay_pcm_irq; } if (stereo && !extra) { snd_emu10k1_ptr_write(emu, CPF, voice, CPF_STEREO_MASK); @@ -360,7 +360,9 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, /* Assumption that PT is already 0 so no harm overwriting */ snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]); snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24)); - snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24)); + snd_emu10k1_ptr_write(emu, PSST, voice, + (start_addr + (extra ? emu->delay_pcm_irq : 0)) | + (send_amount[2] << 24)); if (emu->card_capabilities->emu_model) pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */ else @@ -732,6 +734,23 @@ static void snd_emu10k1_playback_stop_voice(struct snd_emu10k1 *emu, struct snd_ snd_emu10k1_ptr_write(emu, IP, voice, 0); } +static inline void snd_emu10k1_playback_mangle_extra(struct snd_emu10k1 *emu, + struct snd_emu10k1_pcm *epcm, + struct snd_pcm_substream *substream, + struct snd_pcm_runtime *runtime) +{ + unsigned int ptr, period_pos; + + /* try to sychronize the current position for the interrupt + source voice */ + period_pos = runtime->status->hw_ptr - runtime->hw_ptr_interrupt; + period_pos %= runtime->period_size; + ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->extra->number); + ptr &= ~0x00ffffff; + ptr |= epcm->ccca_start_addr + period_pos; + snd_emu10k1_ptr_write(emu, CCCA, epcm->extra->number, ptr); +} + static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, int cmd) { @@ -753,6 +772,8 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, /* follow thru */ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: + if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) + snd_emu10k1_playback_mangle_extra(emu, epcm, substream, runtime); mix = &emu->pcm_mixer[substream->number]; snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0, mix); snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0, mix); @@ -869,8 +890,9 @@ static snd_pcm_uframes_t snd_emu10k1_playback_pointer(struct snd_pcm_substream * #endif /* printk(KERN_DEBUG - "ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", - ptr, runtime->buffer_size, runtime->period_size); + "ptr = 0x%lx, buffer_size = 0x%lx, period_size = 0x%lx\n", + (long)ptr, (long)runtime->buffer_size, + (long)runtime->period_size); */ return ptr; } diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index ffb1ddb8dc28..957a311514c8 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -310,8 +310,10 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst if (snd_BUG_ON(!hdr)) return NULL; + idx = runtime->period_size >= runtime->buffer_size ? + (emu->delay_pcm_irq * 2) : 0; mutex_lock(&hdr->block_mutex); - blk = search_empty(emu, runtime->dma_bytes); + blk = search_empty(emu, runtime->dma_bytes + idx); if (blk == NULL) { mutex_unlock(&hdr->block_mutex); return NULL; -- cgit v1.2.3 From a41c86f225443e29e9d7fb38731eee2873854aab Mon Sep 17 00:00:00 2001 From: Jonathan Woithe Date: Sun, 8 Aug 2010 00:17:05 +0930 Subject: ALSA: hda - Fix missing stream for second ADC on Realtek ALC260 HDA codec commit 53bacfbbb2ddd981287b58a511c8b8f5df179886 upstream. I discovered tonight that ALSA no longer sets up a stream for the second ADC provided by the Realtek ALC260 HDA codec. At some point alc_build_pcms() started using stream_analog_alt_capture when constructing the second ADC stream, but patch_alc260() was never updated accordingly. I have no idea when this regression occurred. The trivial patch to patch_alc260() given below fixes the problem as far as I can tell. The patch is against 2.6.35. Signed-off-by: Jonathan Woithe Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index aa7cc519e7b8..6d9a5424c265 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6864,6 +6864,7 @@ static int patch_alc260(struct hda_codec *codec) spec->stream_analog_playback = &alc260_pcm_analog_playback; spec->stream_analog_capture = &alc260_pcm_analog_capture; + spec->stream_analog_alt_capture = &alc260_pcm_analog_capture; spec->stream_digital_playback = &alc260_pcm_digital_playback; spec->stream_digital_capture = &alc260_pcm_digital_capture; -- cgit v1.2.3 From 94c25715de36c1e1a89f69dbd3b05a0493e77c1f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 16 Aug 2010 10:15:57 +0200 Subject: ALSA: hda - Add quirk for Dell Vostro 1220 commit c3e68fad88143fd1fe8fe640207fb19c0f087dbc upstream. model=dell-vostro is needed for Dell Vostro 1220 with Coexnat 5067. Reference: Novell bnc#631066 https://bugzilla.novell.com/show_bug.cgi?id=631066 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_conexant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 2bf2cb5da956..baadda40f1d0 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -2970,6 +2970,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x1028, 0x02f5, "Dell", CXT5066_DELL_LAPTOP), SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), + SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTO), SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), -- cgit v1.2.3 From 15ddf0fc153f54ed7c8432a18fa1ecde1a32d4bc Mon Sep 17 00:00:00 2001 From: Tiger Yang Date: Fri, 16 Jul 2010 11:21:23 +0800 Subject: ocfs2: do not overwrite error codes in ocfs2_init_acl commit 6eda3dd33f8a0ce58ee56a11351758643a698db4 upstream. Setting the acl while creating a new inode depends on the error codes of posix_acl_create_masq. This patch fix a issue of overwriting the error codes of it. Reported-by: Pawel Zawora Signed-off-by: Tiger Yang Signed-off-by: Joel Becker Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/acl.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index da702294d7e7..5a2177833210 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c @@ -344,7 +344,7 @@ int ocfs2_init_acl(handle_t *handle, { struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct posix_acl *acl = NULL; - int ret = 0; + int ret = 0, ret2; mode_t mode; if (!S_ISLNK(inode->i_mode)) { @@ -381,7 +381,12 @@ int ocfs2_init_acl(handle_t *handle, mode = inode->i_mode; ret = posix_acl_create_masq(clone, &mode); if (ret >= 0) { - ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode); + ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode); + if (ret2) { + mlog_errno(ret2); + ret = ret2; + goto cleanup; + } if (ret > 0) { ret = ocfs2_set_acl(handle, inode, di_bh, ACL_TYPE_ACCESS, -- cgit v1.2.3 From 3730039f40020c1f8d1d94752ecbd1375cf705f9 Mon Sep 17 00:00:00 2001 From: Wengang Wang Date: Fri, 16 Jul 2010 23:13:33 +0800 Subject: ocfs2/dlm: fix a dead lock commit 6d98c3ccb52f692f1a60339dde7c700686a5568b upstream. When we have to take both dlm->master_lock and lockres->spinlock, take them in order lockres->spinlock and then dlm->master_lock. The patch fixes a violation of the rule. We can simply move taking dlm->master_lock to where we have dropped res->spinlock since when we access res->state and free mle memory we don't need master_lock's protection. Signed-off-by: Wengang Wang Signed-off-by: Joel Becker Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/dlm/dlmmaster.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 94b97fc6a88e..6d098b89d46e 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -3050,8 +3050,6 @@ int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data, /* check for pre-existing lock */ spin_lock(&dlm->spinlock); res = __dlm_lookup_lockres(dlm, name, namelen, hash); - spin_lock(&dlm->master_lock); - if (res) { spin_lock(&res->spinlock); if (res->state & DLM_LOCK_RES_RECOVERING) { @@ -3069,14 +3067,15 @@ int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data, spin_unlock(&res->spinlock); } + spin_lock(&dlm->master_lock); /* ignore status. only nonzero status would BUG. */ ret = dlm_add_migration_mle(dlm, res, mle, &oldmle, name, namelen, migrate->new_master, migrate->master); -unlock: spin_unlock(&dlm->master_lock); +unlock: spin_unlock(&dlm->spinlock); if (oldmle) { -- cgit v1.2.3 From caee59ec914e90b06df487fc348fe4780d3c7a34 Mon Sep 17 00:00:00 2001 From: Srinivas Eeda Date: Mon, 19 Jul 2010 16:04:12 -0700 Subject: ocfs2 fix o2dlm dlm run purgelist (rev 3) commit 7beaf243787f85a2ef9213ccf13ab4a243283fde upstream. This patch fixes two problems in dlm_run_purgelist 1. If a lockres is found to be in use, dlm_run_purgelist keeps trying to purge the same lockres instead of trying the next lockres. 2. When a lockres is found unused, dlm_run_purgelist releases lockres spinlock before setting DLM_LOCK_RES_DROPPING_REF and calls dlm_purge_lockres. spinlock is reacquired but in this window lockres can get reused. This leads to BUG. This patch modifies dlm_run_purgelist to skip lockres if it's in use and purge next lockres. It also sets DLM_LOCK_RES_DROPPING_REF before releasing the lockres spinlock protecting it from getting reused. Signed-off-by: Srinivas Eeda Acked-by: Sunil Mushran Signed-off-by: Joel Becker Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/dlm/dlmthread.c | 80 ++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 46 deletions(-) diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c index d4f73ca68fe5..dd78ca3f360f 100644 --- a/fs/ocfs2/dlm/dlmthread.c +++ b/fs/ocfs2/dlm/dlmthread.c @@ -152,45 +152,25 @@ void dlm_lockres_calc_usage(struct dlm_ctxt *dlm, spin_unlock(&dlm->spinlock); } -static int dlm_purge_lockres(struct dlm_ctxt *dlm, +static void dlm_purge_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) { int master; int ret = 0; - spin_lock(&res->spinlock); - if (!__dlm_lockres_unused(res)) { - mlog(0, "%s:%.*s: tried to purge but not unused\n", - dlm->name, res->lockname.len, res->lockname.name); - __dlm_print_one_lock_resource(res); - spin_unlock(&res->spinlock); - BUG(); - } - - if (res->state & DLM_LOCK_RES_MIGRATING) { - mlog(0, "%s:%.*s: Delay dropref as this lockres is " - "being remastered\n", dlm->name, res->lockname.len, - res->lockname.name); - /* Re-add the lockres to the end of the purge list */ - if (!list_empty(&res->purge)) { - list_del_init(&res->purge); - list_add_tail(&res->purge, &dlm->purge_list); - } - spin_unlock(&res->spinlock); - return 0; - } + assert_spin_locked(&dlm->spinlock); + assert_spin_locked(&res->spinlock); master = (res->owner == dlm->node_num); - if (!master) - res->state |= DLM_LOCK_RES_DROPPING_REF; - spin_unlock(&res->spinlock); mlog(0, "purging lockres %.*s, master = %d\n", res->lockname.len, res->lockname.name, master); if (!master) { + res->state |= DLM_LOCK_RES_DROPPING_REF; /* drop spinlock... retake below */ + spin_unlock(&res->spinlock); spin_unlock(&dlm->spinlock); spin_lock(&res->spinlock); @@ -208,31 +188,35 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm, mlog(0, "%s:%.*s: dlm_deref_lockres returned %d\n", dlm->name, res->lockname.len, res->lockname.name, ret); spin_lock(&dlm->spinlock); + spin_lock(&res->spinlock); } - spin_lock(&res->spinlock); if (!list_empty(&res->purge)) { mlog(0, "removing lockres %.*s:%p from purgelist, " "master = %d\n", res->lockname.len, res->lockname.name, res, master); list_del_init(&res->purge); - spin_unlock(&res->spinlock); dlm_lockres_put(res); dlm->purge_count--; - } else - spin_unlock(&res->spinlock); + } + + if (!__dlm_lockres_unused(res)) { + mlog(ML_ERROR, "found lockres %s:%.*s: in use after deref\n", + dlm->name, res->lockname.len, res->lockname.name); + __dlm_print_one_lock_resource(res); + BUG(); + } __dlm_unhash_lockres(res); /* lockres is not in the hash now. drop the flag and wake up * any processes waiting in dlm_get_lock_resource. */ if (!master) { - spin_lock(&res->spinlock); res->state &= ~DLM_LOCK_RES_DROPPING_REF; spin_unlock(&res->spinlock); wake_up(&res->wq); - } - return 0; + } else + spin_unlock(&res->spinlock); } static void dlm_run_purge_list(struct dlm_ctxt *dlm, @@ -251,17 +235,7 @@ static void dlm_run_purge_list(struct dlm_ctxt *dlm, lockres = list_entry(dlm->purge_list.next, struct dlm_lock_resource, purge); - /* Status of the lockres *might* change so double - * check. If the lockres is unused, holding the dlm - * spinlock will prevent people from getting and more - * refs on it -- there's no need to keep the lockres - * spinlock. */ spin_lock(&lockres->spinlock); - unused = __dlm_lockres_unused(lockres); - spin_unlock(&lockres->spinlock); - - if (!unused) - continue; purge_jiffies = lockres->last_used + msecs_to_jiffies(DLM_PURGE_INTERVAL_MS); @@ -273,15 +247,29 @@ static void dlm_run_purge_list(struct dlm_ctxt *dlm, * in tail order, we can stop at the first * unpurgable resource -- anyone added after * him will have a greater last_used value */ + spin_unlock(&lockres->spinlock); break; } + /* Status of the lockres *might* change so double + * check. If the lockres is unused, holding the dlm + * spinlock will prevent people from getting and more + * refs on it. */ + unused = __dlm_lockres_unused(lockres); + if (!unused || + (lockres->state & DLM_LOCK_RES_MIGRATING)) { + mlog(0, "lockres %s:%.*s: is in use or " + "being remastered, used %d, state %d\n", + dlm->name, lockres->lockname.len, + lockres->lockname.name, !unused, lockres->state); + list_move_tail(&dlm->purge_list, &lockres->purge); + spin_unlock(&lockres->spinlock); + continue; + } + dlm_lockres_get(lockres); - /* This may drop and reacquire the dlm spinlock if it - * has to do migration. */ - if (dlm_purge_lockres(dlm, lockres)) - BUG(); + dlm_purge_lockres(dlm, lockres); dlm_lockres_put(lockres); -- cgit v1.2.3 From 6d4ff3b0d4438f1d3707720299c32aa7715a4317 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Thu, 22 Jul 2010 13:56:45 +0800 Subject: ocfs2: Count more refcount records in file system fragmentation. commit 8a2e70c40ff58f82dde67770e6623ca45f0cb0c8 upstream. The refcount record calculation in ocfs2_calc_refcount_meta_credits is too optimistic that we can always allocate contiguous clusters and handle an already existed refcount rec as a whole. Actually because of file system fragmentation, we may have the chance to split a refcount record into 3 parts during the transaction. So consider the worst case in record calculation. Signed-off-by: Tao Ma Signed-off-by: Joel Becker Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/refcounttree.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 3ac5aa733e9c..73a11ccfd4c2 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -2436,16 +2436,26 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb, len = min((u64)cpos + clusters, le64_to_cpu(rec.r_cpos) + le32_to_cpu(rec.r_clusters)) - cpos; /* - * If the refcount rec already exist, cool. We just need - * to check whether there is a split. Otherwise we just need - * to increase the refcount. - * If we will insert one, increases recs_add. - * * We record all the records which will be inserted to the * same refcount block, so that we can tell exactly whether * we need a new refcount block or not. + * + * If we will insert a new one, this is easy and only happens + * during adding refcounted flag to the extent, so we don't + * have a chance of spliting. We just need one record. + * + * If the refcount rec already exists, that would be a little + * complicated. we may have to: + * 1) split at the beginning if the start pos isn't aligned. + * we need 1 more record in this case. + * 2) split int the end if the end pos isn't aligned. + * we need 1 more record in this case. + * 3) split in the middle because of file system fragmentation. + * we need 2 more records in this case(we can't detect this + * beforehand, so always think of the worst case). */ if (rec.r_refcount) { + recs_add += 2; /* Check whether we need a split at the beginning. */ if (cpos == start_cpos && cpos != le64_to_cpu(rec.r_cpos)) -- cgit v1.2.3 From d79caba7b9f51221576fb4afe7dc0e165bdd0485 Mon Sep 17 00:00:00 2001 From: Wengang Wang Date: Fri, 30 Jul 2010 16:14:44 +0800 Subject: ocfs2/dlm: avoid incorrect bit set in refmap on recovery master commit a524812b7eaa7783d7811198921100f079034e61 upstream. In the following situation, there remains an incorrect bit in refmap on the recovery master. Finally the recovery master will fail at purging the lockres due to the incorrect bit in refmap. 1) node A has no interest on lockres A any longer, so it is purging it. 2) the owner of lockres A is node B, so node A is sending de-ref message to node B. 3) at this time, node B crashed. node C becomes the recovery master. it recovers lockres A(because the master is the dead node B). 4) node A migrated lockres A to node C with a refbit there. 5) node A failed to send de-ref message to node B because it crashed. The failure is ignored. no other action is done for lockres A any more. For mormal, re-send the deref message to it to recovery master can fix it. Well, ignoring the failure of deref to the original master and not recovering the lockres to recovery master has the same effect. And the later is simpler. Signed-off-by: Wengang Wang Acked-by: Srinivas Eeda Signed-off-by: Joel Becker Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/dlm/dlmrecovery.c | 22 ++++++++++------------ fs/ocfs2/dlm/dlmthread.c | 34 +++++++++++++++++++++------------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index 9dfaac73b36d..aaaffbcbe916 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c @@ -1997,6 +1997,8 @@ void dlm_move_lockres_to_recovery_list(struct dlm_ctxt *dlm, struct list_head *queue; struct dlm_lock *lock, *next; + assert_spin_locked(&dlm->spinlock); + assert_spin_locked(&res->spinlock); res->state |= DLM_LOCK_RES_RECOVERING; if (!list_empty(&res->recovering)) { mlog(0, @@ -2326,19 +2328,15 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node) /* zero the lvb if necessary */ dlm_revalidate_lvb(dlm, res, dead_node); if (res->owner == dead_node) { - if (res->state & DLM_LOCK_RES_DROPPING_REF) - mlog(0, "%s:%.*s: owned by " - "dead node %u, this node was " - "dropping its ref when it died. " - "continue, dropping the flag.\n", - dlm->name, res->lockname.len, - res->lockname.name, dead_node); - - /* the wake_up for this will happen when the - * RECOVERING flag is dropped later */ - res->state &= ~DLM_LOCK_RES_DROPPING_REF; + if (res->state & DLM_LOCK_RES_DROPPING_REF) { + mlog(ML_NOTICE, "Ignore %.*s for " + "recovery as it is being freed\n", + res->lockname.len, + res->lockname.name); + } else + dlm_move_lockres_to_recovery_list(dlm, + res); - dlm_move_lockres_to_recovery_list(dlm, res); } else if (res->owner == dlm->node_num) { dlm_free_dead_locks(dlm, res, dead_node); __dlm_lockres_calc_usage(dlm, res); diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c index dd78ca3f360f..2211acf33d9b 100644 --- a/fs/ocfs2/dlm/dlmthread.c +++ b/fs/ocfs2/dlm/dlmthread.c @@ -92,19 +92,27 @@ int __dlm_lockres_has_locks(struct dlm_lock_resource *res) * truly ready to be freed. */ int __dlm_lockres_unused(struct dlm_lock_resource *res) { - if (!__dlm_lockres_has_locks(res) && - (list_empty(&res->dirty) && !(res->state & DLM_LOCK_RES_DIRTY))) { - /* try not to scan the bitmap unless the first two - * conditions are already true */ - int bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0); - if (bit >= O2NM_MAX_NODES) { - /* since the bit for dlm->node_num is not - * set, inflight_locks better be zero */ - BUG_ON(res->inflight_locks != 0); - return 1; - } - } - return 0; + int bit; + + if (__dlm_lockres_has_locks(res)) + return 0; + + if (!list_empty(&res->dirty) || res->state & DLM_LOCK_RES_DIRTY) + return 0; + + if (res->state & DLM_LOCK_RES_RECOVERING) + return 0; + + bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0); + if (bit < O2NM_MAX_NODES) + return 0; + + /* + * since the bit for dlm->node_num is not set, inflight_locks better + * be zero + */ + BUG_ON(res->inflight_locks != 0); + return 1; } -- cgit v1.2.3 From 7b5b07e30b8341d54c1f311772c9183eaa1cfa7a Mon Sep 17 00:00:00 2001 From: Wengang Wang Date: Fri, 30 Jul 2010 23:18:00 +0800 Subject: ocfs2/dlm: remove potential deadlock -V3 commit b11f1f1ab73fd358b1b734a9427744802202ba68 upstream. When we need to take both dlm_domain_lock and dlm->spinlock, we should take them in order of: dlm_domain_lock then dlm->spinlock. There is pathes disobey this order. That is calling dlm_lockres_put() with dlm->spinlock held in dlm_run_purge_list. dlm_lockres_put() calls dlm_put() at the ref and dlm_put() locks on dlm_domain_lock. Fix: Don't grab/put the dlm when the initialising/releasing lockres. That grab is not required because we don't call dlm_unregister_domain() based on refcount. Signed-off-by: Wengang Wang Signed-off-by: Joel Becker Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/dlm/dlmmaster.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 6d098b89d46e..ffb4c68dafa4 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -511,8 +511,6 @@ static void dlm_lockres_release(struct kref *kref) atomic_dec(&dlm->res_cur_count); - dlm_put(dlm); - if (!hlist_unhashed(&res->hash_node) || !list_empty(&res->granted) || !list_empty(&res->converting) || @@ -585,8 +583,6 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm, res->migration_pending = 0; res->inflight_locks = 0; - /* put in dlm_lockres_release */ - dlm_grab(dlm); res->dlm = dlm; kref_init(&res->refs); -- cgit v1.2.3 From 208348a42d2c5027b66e49d78ddc0548bd0193f2 Mon Sep 17 00:00:00 2001 From: Yuri Kululin Date: Fri, 13 Aug 2010 13:46:12 +0400 Subject: wl1251: fix trigger scan timeout usage commit fe0dbcc9d2e941328b3269dab102b94ad697ade5 upstream. Use appropriate command (CMD_TRIGGER_SCAN_TO) instead of scan command (CMD_SCAN) to configure trigger scan timeout. This was broken in commit 3a98c30f3e8bb1f32b5bcb74a39647b3670de275. This fix address the bug reported here: https://bugzilla.kernel.org/show_bug.cgi?id=16554 Signed-off-by: Yuri Ershov Signed-off-by: Yuri Kululin Acked-by: Kalle Valo Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/wl12xx/wl1251_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c index a37b30cef489..ce3722f4c3e3 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.c @@ -484,7 +484,7 @@ int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout) cmd->timeout = timeout; - ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd)); + ret = wl1251_cmd_send(wl, CMD_TRIGGER_SCAN_TO, cmd, sizeof(*cmd)); if (ret < 0) { wl1251_error("cmd trigger scan to failed: %d", ret); goto out; -- cgit v1.2.3 From 3ab47fa1a288f370ced9e9575655151df20c04fc Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Fri, 13 Aug 2010 12:42:24 +0900 Subject: nilfs2: fix list corruption after ifile creation failure commit af4e36318edb848fcc0a8d5f75000ca00cdc7595 upstream. If nilfs_attach_checkpoint() gets a memory allocation failure during creation of ifile, it will return without removing nilfs_sb_info struct from ns_supers list. When a concurrently mounted snapshot is unmounted or another new snapshot is mounted after that, this causes kernel oops as below: > BUG: unable to handle kernel NULL pointer dereference at (null) > IP: [] nilfs_find_sbinfo+0x74/0xa4 [nilfs2] > *pde = 00000000 > Oops: 0000 [#1] SMP > Call Trace: > [] ? nilfs_get_sb+0x165/0x532 [nilfs2] > [] ? ida_get_new_above+0x16d/0x187 > [] ? alloc_vfsmnt+0x7e/0x10a > [] ? kstrdup+0x2c/0x40 > [] ? vfs_kern_mount+0x96/0x14e > [] ? do_kern_mount+0x32/0xbd > [] ? do_mount+0x642/0x6a1 > [] ? do_page_fault+0x0/0x2d1 > [] ? copy_mount_options+0x80/0xe2 > [] ? strndup_user+0x48/0x67 > [] ? sys_mount+0x61/0x90 > [] ? sysenter_do_call+0x12/0x22 This fixes the problem. Signed-off-by: Ryusuke Konishi Tested-by: Ryusuke Konishi Signed-off-by: Greg Kroah-Hartman --- fs/nilfs2/super.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 414ef68931cf..fbb354c36e69 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -336,9 +336,10 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) list_add(&sbi->s_list, &nilfs->ns_supers); up_write(&nilfs->ns_super_sem); + err = -ENOMEM; sbi->s_ifile = nilfs_ifile_new(sbi, nilfs->ns_inode_size); if (!sbi->s_ifile) - return -ENOMEM; + goto delist; down_read(&nilfs->ns_segctor_sem); err = nilfs_cpfile_get_checkpoint(nilfs->ns_cpfile, cno, 0, &raw_cp, @@ -369,6 +370,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) nilfs_mdt_destroy(sbi->s_ifile); sbi->s_ifile = NULL; + delist: down_write(&nilfs->ns_super_sem); list_del_init(&sbi->s_list); up_write(&nilfs->ns_super_sem); -- cgit v1.2.3 From ee384c27819972c620c2eec0545b9f1472cbe0ab Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Tue, 27 Jul 2010 16:06:34 +0800 Subject: tracing: Fix an unallocated memory access in function_graph commit 575570f02761bd680ba5731c1dfd4701062e7fb2 upstream. With CONFIG_DEBUG_PAGEALLOC, I observed an unallocated memory access in function_graph trace. It appears we find a small size entry in ring buffer, but we access it as a big size entry. The access overflows the page size and touches an unallocated page. Signed-off-by: Shaohua Li LKML-Reference: <1280217994.32400.76.camel@sli10-desk.sh.intel.com> [ Added a comment to explain the problem - SDR ] Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/trace/trace_functions_graph.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 79f4bac99a94..b4c179ae4e45 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c @@ -507,7 +507,15 @@ get_return_for_leaf(struct trace_iterator *iter, * if the output fails. */ data->ent = *curr; - data->ret = *next; + /* + * If the next event is not a return type, then + * we only care about what type it is. Otherwise we can + * safely copy the entire event. + */ + if (next->ent.type == TRACE_GRAPH_RET) + data->ret = *next; + else + data->ret.ent.type = next->ent.type; } } -- cgit v1.2.3 From 19d3c4671fabe2b80e6d449f88dd1822b6be66da Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Wed, 28 Jul 2010 14:14:01 +0800 Subject: tracing: Fix ring_buffer_read_page reading out of page boundary commit 18fab912d4fa70133df164d2dcf3310be0c38c34 upstream. With the configuration: CONFIG_DEBUG_PAGEALLOC=y and Shaohua's patch: [PATCH]x86: make spurious_fault check correct pte bit Function call graph trace with the following will trigger a page fault. # cd /sys/kernel/debug/tracing/ # echo function_graph > current_tracer # cat per_cpu/cpu1/trace_pipe_raw > /dev/null BUG: unable to handle kernel paging request at ffff880006e99000 IP: [] rb_event_length+0x1/0x3f PGD 1b19063 PUD 1b1d063 PMD 3f067 PTE 6e99160 Oops: 0000 [#1] SMP DEBUG_PAGEALLOC last sysfs file: /sys/devices/virtual/net/lo/operstate CPU 1 Modules linked in: Pid: 1982, comm: cat Not tainted 2.6.35-rc6-aes+ #300 /Bochs RIP: 0010:[] [] rb_event_length+0x1/0x3f RSP: 0018:ffff880006475e38 EFLAGS: 00010006 RAX: 0000000000000ff0 RBX: ffff88000786c630 RCX: 000000000000001d RDX: ffff880006e98000 RSI: 0000000000000ff0 RDI: ffff880006e99000 RBP: ffff880006475eb8 R08: 000000145d7008bd R09: 0000000000000000 R10: 0000000000008000 R11: ffffffff815d9336 R12: ffff880006d08000 R13: ffff880006e605d8 R14: 0000000000000000 R15: 0000000000000018 FS: 00007f2b83e456f0(0000) GS:ffff880002100000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: ffff880006e99000 CR3: 00000000064a8000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process cat (pid: 1982, threadinfo ffff880006474000, task ffff880006e40770) Stack: ffff880006475eb8 ffffffff8108730f 0000000000000ff0 000000145d7008bd <0> ffff880006e98010 ffff880006d08010 0000000000000296 ffff88000786c640 <0> ffffffff81002956 0000000000000000 ffff8800071f4680 ffff8800071f4680 Call Trace: [] ? ring_buffer_read_page+0x15a/0x24a [] ? return_to_handler+0x15/0x2f [] tracing_buffers_read+0xb9/0x164 [] vfs_read+0xaf/0x150 [] return_to_handler+0x0/0x2f [] __bad_area_nosemaphore+0x17e/0x1a1 [] return_to_handler+0x0/0x2f [] bad_area_nosemaphore+0x13/0x15 Code: 80 25 b2 16 b3 00 fe c9 c3 55 48 89 e5 f0 80 0d a4 16 b3 00 02 c9 c3 55 31 c0 48 89 e5 48 83 3d 94 16 b3 00 01 c9 0f 94 c0 c3 55 <8a> 0f 48 89 e5 83 e1 1f b8 08 00 00 00 0f b6 d1 83 fa 1e 74 27 RIP [] rb_event_length+0x1/0x3f RSP CR2: ffff880006e99000 ---[ end trace a6877bb92ccb36bb ]--- The root cause is that ring_buffer_read_page() may read out of page boundary, because the boundary checking is done after reading. This is fixed via doing boundary checking before reading. Reported-by: Shaohua Li Signed-off-by: Huang Ying LKML-Reference: <1280297641.2771.307.camel@yhuang-dev> Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/trace/ring_buffer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 1da7b6ea8b85..5ec8f1d1480e 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -3868,6 +3868,9 @@ int ring_buffer_read_page(struct ring_buffer *buffer, rpos = reader->read; pos += size; + if (rpos >= commit) + break; + event = rb_reader_event(cpu_buffer); size = rb_event_length(event); } while (len > size); -- cgit v1.2.3 From 57001f2240b0cba6ec95f460da34c0e81f52b4c2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 9 Aug 2010 15:52:03 +0200 Subject: cfg80211: fix locking in action frame TX commit fe100acddf438591ecf3582cb57241e560da70b7 upstream. Accesses to "wdev->current_bss" must be locked with the wdev lock, which action frame transmission is missing. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/wireless/mlme.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index ef17fcf85092..e4be68876184 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -842,12 +842,18 @@ int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, return -EINVAL; if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) { /* Verify that we are associated with the destination AP */ + wdev_lock(wdev); + if (!wdev->current_bss || memcmp(wdev->current_bss->pub.bssid, mgmt->bssid, ETH_ALEN) != 0 || memcmp(wdev->current_bss->pub.bssid, mgmt->da, - ETH_ALEN) != 0) + ETH_ALEN) != 0) { + wdev_unlock(wdev); return -ENOTCONN; + } + wdev_unlock(wdev); + } if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0) -- cgit v1.2.3 From edda4cb2d00bfb83759f475ff9b228953ea82cf2 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Fri, 6 Aug 2010 04:04:38 +0200 Subject: x86, asm: Refactor atomic64_386_32.S to support old binutils and be cleaner commit 30246557a06bb20618bed906a06d1e1e0faa8bb4 upstream. The old code didn't work on binutils 2.12 because setting a symbol to a register apparently requires a fairly recent version. This commit refactors the code to use the C preprocessor instead, and in the process makes the whole code a bit easier to understand. The object code produced is unchanged as expected. This fixes kernel bugzilla 16506. Reported-by: Dieter Stussy Signed-off-by: Luca Barbieri Signed-off-by: H. Peter Anvin LKML-Reference: Signed-off-by: Greg Kroah-Hartman --- arch/x86/lib/atomic64_386_32.S | 236 ++++++++++++++++++++++------------------- 1 file changed, 128 insertions(+), 108 deletions(-) diff --git a/arch/x86/lib/atomic64_386_32.S b/arch/x86/lib/atomic64_386_32.S index 4a5979aa6883..78ee8e0fa278 100644 --- a/arch/x86/lib/atomic64_386_32.S +++ b/arch/x86/lib/atomic64_386_32.S @@ -25,150 +25,170 @@ CFI_ADJUST_CFA_OFFSET -4 .endm -.macro BEGIN func reg -$v = \reg - -ENTRY(atomic64_\func\()_386) - CFI_STARTPROC - LOCK $v - -.macro RETURN - UNLOCK $v +#define BEGIN(op) \ +.macro END; \ + CFI_ENDPROC; \ +ENDPROC(atomic64_##op##_386); \ +.purgem END; \ +.endm; \ +ENTRY(atomic64_##op##_386); \ + CFI_STARTPROC; \ + LOCK v; + +#define RET \ + UNLOCK v; \ ret -.endm - -.macro END_ - CFI_ENDPROC -ENDPROC(atomic64_\func\()_386) -.purgem RETURN -.purgem END_ -.purgem END -.endm - -.macro END -RETURN -END_ -.endm -.endm - -BEGIN read %ecx - movl ($v), %eax - movl 4($v), %edx -END - -BEGIN set %esi - movl %ebx, ($v) - movl %ecx, 4($v) -END - -BEGIN xchg %esi - movl ($v), %eax - movl 4($v), %edx - movl %ebx, ($v) - movl %ecx, 4($v) -END - -BEGIN add %ecx - addl %eax, ($v) - adcl %edx, 4($v) -END -BEGIN add_return %ecx - addl ($v), %eax - adcl 4($v), %edx - movl %eax, ($v) - movl %edx, 4($v) -END - -BEGIN sub %ecx - subl %eax, ($v) - sbbl %edx, 4($v) -END - -BEGIN sub_return %ecx +#define RET_END \ + RET; \ + END + +#define v %ecx +BEGIN(read) + movl (v), %eax + movl 4(v), %edx +RET_END +#undef v + +#define v %esi +BEGIN(set) + movl %ebx, (v) + movl %ecx, 4(v) +RET_END +#undef v + +#define v %esi +BEGIN(xchg) + movl (v), %eax + movl 4(v), %edx + movl %ebx, (v) + movl %ecx, 4(v) +RET_END +#undef v + +#define v %ecx +BEGIN(add) + addl %eax, (v) + adcl %edx, 4(v) +RET_END +#undef v + +#define v %ecx +BEGIN(add_return) + addl (v), %eax + adcl 4(v), %edx + movl %eax, (v) + movl %edx, 4(v) +RET_END +#undef v + +#define v %ecx +BEGIN(sub) + subl %eax, (v) + sbbl %edx, 4(v) +RET_END +#undef v + +#define v %ecx +BEGIN(sub_return) negl %edx negl %eax sbbl $0, %edx - addl ($v), %eax - adcl 4($v), %edx - movl %eax, ($v) - movl %edx, 4($v) -END - -BEGIN inc %esi - addl $1, ($v) - adcl $0, 4($v) -END - -BEGIN inc_return %esi - movl ($v), %eax - movl 4($v), %edx + addl (v), %eax + adcl 4(v), %edx + movl %eax, (v) + movl %edx, 4(v) +RET_END +#undef v + +#define v %esi +BEGIN(inc) + addl $1, (v) + adcl $0, 4(v) +RET_END +#undef v + +#define v %esi +BEGIN(inc_return) + movl (v), %eax + movl 4(v), %edx addl $1, %eax adcl $0, %edx - movl %eax, ($v) - movl %edx, 4($v) -END - -BEGIN dec %esi - subl $1, ($v) - sbbl $0, 4($v) -END - -BEGIN dec_return %esi - movl ($v), %eax - movl 4($v), %edx + movl %eax, (v) + movl %edx, 4(v) +RET_END +#undef v + +#define v %esi +BEGIN(dec) + subl $1, (v) + sbbl $0, 4(v) +RET_END +#undef v + +#define v %esi +BEGIN(dec_return) + movl (v), %eax + movl 4(v), %edx subl $1, %eax sbbl $0, %edx - movl %eax, ($v) - movl %edx, 4($v) -END + movl %eax, (v) + movl %edx, 4(v) +RET_END +#undef v -BEGIN add_unless %ecx +#define v %ecx +BEGIN(add_unless) addl %eax, %esi adcl %edx, %edi - addl ($v), %eax - adcl 4($v), %edx + addl (v), %eax + adcl 4(v), %edx cmpl %eax, %esi je 3f 1: - movl %eax, ($v) - movl %edx, 4($v) + movl %eax, (v) + movl %edx, 4(v) movl $1, %eax 2: -RETURN + RET 3: cmpl %edx, %edi jne 1b xorl %eax, %eax jmp 2b -END_ +END +#undef v -BEGIN inc_not_zero %esi - movl ($v), %eax - movl 4($v), %edx +#define v %esi +BEGIN(inc_not_zero) + movl (v), %eax + movl 4(v), %edx testl %eax, %eax je 3f 1: addl $1, %eax adcl $0, %edx - movl %eax, ($v) - movl %edx, 4($v) + movl %eax, (v) + movl %edx, 4(v) movl $1, %eax 2: -RETURN + RET 3: testl %edx, %edx jne 1b jmp 2b -END_ +END +#undef v -BEGIN dec_if_positive %esi - movl ($v), %eax - movl 4($v), %edx +#define v %esi +BEGIN(dec_if_positive) + movl (v), %eax + movl 4(v), %edx subl $1, %eax sbbl $0, %edx js 1f - movl %eax, ($v) - movl %edx, 4($v) + movl %eax, (v) + movl %edx, 4(v) 1: -END +RET_END +#undef v -- cgit v1.2.3 From e77930c78bd9dde017a80f87e2a89d670be19202 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Thu, 5 Aug 2010 19:09:17 +0400 Subject: perf, x86: P4 PMU -- update nmi irq statistics and unmask lvt entry properly commit 1c250d709fdc8aa5bf42d90be99428a01a256a55 upstream. In case if last active performance counter is not overflowed at moment of NMI being triggered by another counter, the irq statistics may miss an update stage. As a more serious consequence -- apic quirk may not be triggered so apic lvt entry stay masked. Tested-by: Lin Ming Signed-off-by: Cyrill Gorcunov Cc: Stephane Eranian Cc: Peter Zijlstra Cc: Frederic Weisbecker LKML-Reference: <20100805150917.GA6311@lenovo> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/perf_event_p4.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index ae85d69644d1..0ffe19e9373a 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -581,6 +581,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs) cpuc = &__get_cpu_var(cpu_hw_events); for (idx = 0; idx < x86_pmu.num_counters; idx++) { + int overflow; if (!test_bit(idx, cpuc->active_mask)) continue; @@ -591,12 +592,14 @@ static int p4_pmu_handle_irq(struct pt_regs *regs) WARN_ON_ONCE(hwc->idx != idx); /* it might be unflagged overflow */ - handled = p4_pmu_clear_cccr_ovf(hwc); + overflow = p4_pmu_clear_cccr_ovf(hwc); val = x86_perf_event_update(event); - if (!handled && (val & (1ULL << (x86_pmu.cntval_bits - 1)))) + if (!overflow && (val & (1ULL << (x86_pmu.cntval_bits - 1)))) continue; + handled += overflow; + /* event overflow for sure */ data.period = event->hw.last_period; @@ -612,7 +615,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs) inc_irq_stat(apic_perf_irqs); } - return handled; + return handled > 0; } /* -- cgit v1.2.3 From 7811db7b800fea7a8d85045445d12a6ab639f806 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 4 Aug 2010 13:30:27 -0700 Subject: x86, apic: Map the local apic when parsing the MP table. commit 5989cd6a1cbf86587edcc856791f960978087311 upstream. This fixes a regression in 2.6.35 from 2.6.34, that is present for select models of Intel cpus when people are using an MP table. The commit cf7500c0ea133d66f8449d86392d83f840102632 "x86, ioapic: In mpparse use mp_register_ioapic" started calling mp_register_ioapic from MP_ioapic_info. An extremely simple change that was obviously correct. Unfortunately mp_register_ioapic did just a little more than the previous hand crafted code and so we gained this call path. The problem call path is: MP_ioapic_info() mp_register_ioapic() io_apic_unique_id() io_apic_get_unique_id() get_physical_broadcast() modern_apic() lapic_get_version() apic_read(APIC_LVR) Which turned out to be a problem because the local apic was not mapped, at that point, unlike the similar point in the ACPI parsing code. This problem is fixed by mapping the local apic when parsing the mptable as soon as we reasonably can. Looking at the number of places we setup the fixmap for the local apic, I see some serious simplification opportunities. For the moment except for not duplicating the setting up of the fixmap in init_apic_mappings, I have not acted on them. The regression from 2.6.34 is tracked in bug https://bugzilla.kernel.org/show_bug.cgi?id=16173 Reported-by: David Hill Reported-by: Tvrtko Ursulin Tested-by: Tvrtko Ursulin Signed-off-by: Eric W. Biederman LKML-Reference: Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/apic/apic.c | 2 +- arch/x86/kernel/mpparse.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index a96489ee6cab..c07e51391a3f 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1606,7 +1606,7 @@ void __init init_apic_mappings(void) * acpi lapic path already maps that address in * acpi_register_lapic_address() */ - if (!acpi_lapic) + if (!acpi_lapic && !smp_found_config) set_fixmap_nocache(FIX_APIC_BASE, apic_phys); apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n", diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index d86dbf7e54be..d7b6f7fb4fec 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -274,6 +274,18 @@ static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt) void __init default_smp_read_mpc_oem(struct mpc_table *mpc) { } +static void __init smp_register_lapic_address(unsigned long address) +{ + mp_lapic_addr = address; + + set_fixmap_nocache(FIX_APIC_BASE, address); + if (boot_cpu_physical_apicid == -1U) { + boot_cpu_physical_apicid = read_apic_id(); + apic_version[boot_cpu_physical_apicid] = + GET_APIC_VERSION(apic_read(APIC_LVR)); + } +} + static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) { char str[16]; @@ -295,6 +307,10 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) if (early) return 1; + /* Initialize the lapic mapping */ + if (!acpi_lapic) + smp_register_lapic_address(mpc->lapic); + if (mpc->oemptr) x86_init.mpparse.smp_read_mpc_oem(mpc); -- cgit v1.2.3 From 7e817098c960644260d1142d6bae7ae7ee8070fe Mon Sep 17 00:00:00 2001 From: Victor van den Elzen Date: Sun, 15 Aug 2010 01:19:33 +0200 Subject: platform/x86: move rfkill for Dell Mini 1012 to compal-laptop commit c3f755e3842108c1cffe570fe9802239810352b6 upstream. Like others in the Mini series, the Dell Mini 1012 does not support the smbios hook required by dell-laptop. Signed-off-by: Victor van den Elzen Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/compal-laptop.c | 9 +++++++++ drivers/platform/x86/dell-laptop.c | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c index 71ff1545a93e..90111d71db60 100644 --- a/drivers/platform/x86/compal-laptop.c +++ b/drivers/platform/x86/compal-laptop.c @@ -258,6 +258,14 @@ static struct dmi_system_id __initdata compal_dmi_table[] = { }, .callback = dmi_check_cb }, + { + .ident = "Dell Mini 1012", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"), + }, + .callback = dmi_check_cb + }, { .ident = "Dell Inspiron 11z", .matches = { @@ -375,5 +383,6 @@ MODULE_ALIAS("dmi:*:rnIFT00:rvrIFT00:*"); MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron910:*"); MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1010:*"); MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1011:*"); +MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1012:*"); MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1110:*"); MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1210:*"); diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 661e3ac4d5b1..61106019214d 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -115,6 +115,13 @@ static struct dmi_system_id __devinitdata dell_blacklist[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"), }, }, + { + .ident = "Dell Mini 1012", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"), + }, + }, { .ident = "Dell Inspiron 11z", .matches = { -- cgit v1.2.3 From 6105020a90881ab1916a632532948255c9d28a8f Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 19 Aug 2010 20:10:29 +0200 Subject: x86, hotplug: Serialize CPU hotplug to avoid bringup concurrency issues commit d7c53c9e822a4fefa13a0cae76f3190bfd0d5c11 upstream. When testing cpu hotplug code on 32-bit we kept hitting the "CPU%d: Stuck ??" message due to multiple cores concurrently accessing the cpu_callin_mask, among others. Since these codepaths are not protected from concurrent access due to the fact that there's no sane reason for making an already complex code unnecessarily more complex - we hit the issue only when insanely switching cores off- and online - serialize hotplugging cores on the sysfs level and be done with it. [ v2.1: fix !HOTPLUG_CPU build ] Signed-off-by: Borislav Petkov LKML-Reference: <20100819181029.GC17171@aftab> Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/Kconfig | 5 +++++ arch/x86/kernel/smpboot.c | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index dcb0593b4a66..f942bb713a3d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -247,6 +247,11 @@ config ARCH_HWEIGHT_CFLAGS config KTIME_SCALAR def_bool X86_32 + +config ARCH_CPU_PROBE_RELEASE + def_bool y + depends on HOTPLUG_CPU + source "init/Kconfig" source "kernel/Kconfig.freezer" diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 11015fd1abbc..0bf2ece9982f 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -91,6 +91,25 @@ DEFINE_PER_CPU(int, cpu_state) = { 0 }; static DEFINE_PER_CPU(struct task_struct *, idle_thread_array); #define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x)) #define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p)) + +/* + * We need this for trampoline_base protection from concurrent accesses when + * off- and onlining cores wildly. + */ +static DEFINE_MUTEX(x86_cpu_hotplug_driver_mutex); + +void cpu_hotplug_driver_lock() +{ + mutex_lock(&x86_cpu_hotplug_driver_mutex); +} + +void cpu_hotplug_driver_unlock() +{ + mutex_unlock(&x86_cpu_hotplug_driver_mutex); +} + +ssize_t arch_cpu_probe(const char *buf, size_t count) { return -1; } +ssize_t arch_cpu_release(const char *buf, size_t count) { return -1; } #else static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; #define get_idle_for_cpu(x) (idle_thread_array[(x)]) -- cgit v1.2.3 From 05a939449fc6998700eb5264feee9206a6d6e6f6 Mon Sep 17 00:00:00 2001 From: "Zhang, Yanmin" Date: Fri, 6 Aug 2010 13:39:08 +0800 Subject: perf, x86: Fix Intel-nhm PMU programming errata workaround commit 351af0725e5222e35741011d1ea62215c1ed06db upstream. Fix the Errata AAK100/AAP53/BD53 workaround, the officialy documented workaround we implemented in: 11164cd: perf, x86: Add Nehelem PMU programming errata workaround doesn't actually work fully and causes a stuck PMU state under load and non-functioning perf profiling. A functional workaround was found by trial & error. Affects all Nehalem-class Intel PMUs. Signed-off-by: Zhang Yanmin Signed-off-by: Peter Zijlstra LKML-Reference: <1281073148.2125.63.camel@ymzhang.sh.intel.com> Cc: Arjan van de Ven Cc: "H. Peter Anvin" Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/perf_event_intel.c | 81 ++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 18 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 214ac860ebe0..d8d86d014008 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -491,33 +491,78 @@ static void intel_pmu_enable_all(int added) * Intel Errata AAP53 (model 30) * Intel Errata BD53 (model 44) * - * These chips need to be 'reset' when adding counters by programming - * the magic three (non counting) events 0x4300D2, 0x4300B1 and 0x4300B5 - * either in sequence on the same PMC or on different PMCs. + * The official story: + * These chips need to be 'reset' when adding counters by programming the + * magic three (non-counting) events 0x4300B5, 0x4300D2, and 0x4300B1 either + * in sequence on the same PMC or on different PMCs. + * + * In practise it appears some of these events do in fact count, and + * we need to programm all 4 events. */ -static void intel_pmu_nhm_enable_all(int added) +static void intel_pmu_nhm_workaround(void) { - if (added) { - struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); - int i; + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + static const unsigned long nhm_magic[4] = { + 0x4300B5, + 0x4300D2, + 0x4300B1, + 0x4300B1 + }; + struct perf_event *event; + int i; + + /* + * The Errata requires below steps: + * 1) Clear MSR_IA32_PEBS_ENABLE and MSR_CORE_PERF_GLOBAL_CTRL; + * 2) Configure 4 PERFEVTSELx with the magic events and clear + * the corresponding PMCx; + * 3) set bit0~bit3 of MSR_CORE_PERF_GLOBAL_CTRL; + * 4) Clear MSR_CORE_PERF_GLOBAL_CTRL; + * 5) Clear 4 pairs of ERFEVTSELx and PMCx; + */ + + /* + * The real steps we choose are a little different from above. + * A) To reduce MSR operations, we don't run step 1) as they + * are already cleared before this function is called; + * B) Call x86_perf_event_update to save PMCx before configuring + * PERFEVTSELx with magic number; + * C) With step 5), we do clear only when the PERFEVTSELx is + * not used currently. + * D) Call x86_perf_event_set_period to restore PMCx; + */ - wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + 0, 0x4300D2); - wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + 1, 0x4300B1); - wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + 2, 0x4300B5); + /* We always operate 4 pairs of PERF Counters */ + for (i = 0; i < 4; i++) { + event = cpuc->events[i]; + if (event) + x86_perf_event_update(event); + } - wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0x3); - wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0x0); + for (i = 0; i < 4; i++) { + wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + i, nhm_magic[i]); + wrmsrl(MSR_ARCH_PERFMON_PERFCTR0 + i, 0x0); + } - for (i = 0; i < 3; i++) { - struct perf_event *event = cpuc->events[i]; + wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0xf); + wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0x0); - if (!event) - continue; + for (i = 0; i < 4; i++) { + event = cpuc->events[i]; + if (event) { + x86_perf_event_set_period(event); __x86_pmu_enable_event(&event->hw, - ARCH_PERFMON_EVENTSEL_ENABLE); - } + ARCH_PERFMON_EVENTSEL_ENABLE); + } else + wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + i, 0x0); } +} + +static void intel_pmu_nhm_enable_all(int added) +{ + if (added) + intel_pmu_nhm_workaround(); intel_pmu_enable_all(added); } -- cgit v1.2.3 From 236550e70368f7fb5f854d5a59aa16e13f169a06 Mon Sep 17 00:00:00 2001 From: Daniel Kiper Date: Fri, 20 Aug 2010 00:46:16 +0200 Subject: x86, apic: Fix apic=debug boot crash commit 05e407603e527f9d808dd3866d3a17c2ce4dfcc5 upstream. Fix a boot crash when apic=debug is used and the APIC is not properly initialized. This issue appears during Xen Dom0 kernel boot but the fix is generic and the crash could occur on real hardware as well. Signed-off-by: Daniel Kiper Cc: xen-devel@lists.xensource.com Cc: konrad.wilk@oracle.com Cc: jeremy@goop.org LKML-Reference: <20100819224616.GB9967@router-fw-old.local.net-space.pl> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/apic/io_apic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index e41ed24ab26d..2b18af15b3dd 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1728,6 +1728,8 @@ __apicdebuginit(void) print_IO_APIC(void) struct irq_pin_list *entry; cfg = desc->chip_data; + if (!cfg) + continue; entry = cfg->irq_2_pin; if (!entry) continue; -- cgit v1.2.3 From 53aaf5f20c73f7f35364aaefc01494b9cbe460b9 Mon Sep 17 00:00:00 2001 From: Jiaju Zhang Date: Wed, 28 Jul 2010 13:21:06 +0800 Subject: Fix the nested PR lock calling issue in ACL commit 845b6cf34150100deb5f58c8a37a372b111f2918 upstream. Hi, Thanks a lot for all the review and comments so far;) I'd like to send the improved (V4) version of this patch. This patch fixes a deadlock in OCFS2 ACL. We found this bug in OCFS2 and Samba integration using scenario, the symptom is several smbd processes will be hung under heavy workload. Finally we found out it is the nested PR lock calling that leads to this deadlock: node1 node2 gr PR | V PR(EX)---> BAST:OCFS2_LOCK_BLOCKED | V rq PR | V wait=1 After requesting the 2nd PR lock, the process "smbd" went into D state. It can only be woken up when the 1st PR lock's RO holder equals zero. There should be an ocfs2_inode_unlock in the calling path later on, which can decrement the RO holder. But since it has been in uninterruptible sleep, the unlock function has no chance to be called. The related stack trace is: smbd D ffff8800013d0600 0 9522 5608 0x00000000 ffff88002ca7fb18 0000000000000282 ffff88002f964500 ffff88002ca7fa98 ffff8800013d0600 ffff88002ca7fae0 ffff88002f964340 ffff88002f964340 ffff88002ca7ffd8 ffff88002ca7ffd8 ffff88002f964340 ffff88002f964340 Call Trace: [] schedule_timeout+0x175/0x210 [] wait_for_common+0xf0/0x210 [] __ocfs2_cluster_lock+0x3b9/0xa90 [ocfs2] [] ocfs2_inode_lock_full_nested+0x255/0xdb0 [ocfs2] [] ocfs2_get_acl+0x69/0x120 [ocfs2] [] ocfs2_check_acl+0x28/0x80 [ocfs2] [] acl_permission_check+0x57/0xb0 [] generic_permission+0x1d/0xc0 [] ocfs2_permission+0x10a/0x1d0 [ocfs2] [] inode_permission+0x45/0x100 [] sys_chdir+0x53/0x90 [] system_call_fastpath+0x16/0x1b [<00007f34a4ef6927>] 0x7f34a4ef6927 For details, please see: https://bugzilla.novell.com/show_bug.cgi?id=614332 and http://oss.oracle.com/bugzilla/show_bug.cgi?id=1278 Signed-off-by: Jiaju Zhang Acked-by: Mark Fasheh Signed-off-by: Joel Becker Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/acl.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index 5a2177833210..a76e0aa5cd3f 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c @@ -290,12 +290,30 @@ static int ocfs2_set_acl(handle_t *handle, int ocfs2_check_acl(struct inode *inode, int mask) { - struct posix_acl *acl = ocfs2_get_acl(inode, ACL_TYPE_ACCESS); + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); + struct buffer_head *di_bh = NULL; + struct posix_acl *acl; + int ret = -EAGAIN; - if (IS_ERR(acl)) + if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) + return ret; + + ret = ocfs2_read_inode_block(inode, &di_bh); + if (ret < 0) { + mlog_errno(ret); + return ret; + } + + acl = ocfs2_get_acl_nolock(inode, ACL_TYPE_ACCESS, di_bh); + + brelse(di_bh); + + if (IS_ERR(acl)) { + mlog_errno(PTR_ERR(acl)); return PTR_ERR(acl); + } if (acl) { - int ret = posix_acl_permission(inode, acl, mask); + ret = posix_acl_permission(inode, acl, mask); posix_acl_release(acl); return ret; } -- cgit v1.2.3 From 03dc7fc1b97851c561f4ca5617921dbd870434a0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 6 Aug 2010 00:27:44 -0400 Subject: drm/radeon/kms: add additional quirk for Acer rv620 laptop commit 9ea2c4be978d597076ddc6c550557de5d243cea8 upstream. HPD pins are reversed Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=29387 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_atombios.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 10673ae59cfa..a05024959b03 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -206,6 +206,7 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, uint16_t *line_mux, struct radeon_hpd *hpd) { + struct radeon_device *rdev = dev->dev_private; /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ if ((dev->pdev->device == 0x791e) && @@ -308,13 +309,22 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, } } - /* Acer laptop reports DVI-D as DVI-I */ + /* Acer laptop reports DVI-D as DVI-I and hpd pins reversed */ if ((dev->pdev->device == 0x95c4) && (dev->pdev->subsystem_vendor == 0x1025) && (dev->pdev->subsystem_device == 0x013c)) { + struct radeon_gpio_rec gpio; + if ((*connector_type == DRM_MODE_CONNECTOR_DVII) && - (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) + (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) { + gpio = radeon_lookup_gpio(rdev, 6); + *hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio); *connector_type = DRM_MODE_CONNECTOR_DVID; + } else if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) && + (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) { + gpio = radeon_lookup_gpio(rdev, 7); + *hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio); + } } /* XFX Pine Group device rv730 reports no VGA DDC lines -- cgit v1.2.3 From 3770619e38c3ccdc38cf7635f5b958eca73ca284 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Mon, 2 Aug 2010 09:43:52 +1000 Subject: drm/radeon/kms: add missing copy from user commit d8ab35575098b2d6dc10b2535aeb40545933ae56 upstream. This hasn't mattered up until the ioctl started using the value, and it fell apart. fixes fd.o 29340, Ubuntu LP 606081 [airlied: cleaned up whitespace and don't need an error before pushing] Signed-off-by: Dr. David Alan Gilbert Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_kms.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index ab389f89fa8d..b20379e04a9c 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -106,7 +106,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) info = data; value_ptr = (uint32_t *)((unsigned long)info->value); - value = *value_ptr; + if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) + return -EFAULT; + switch (info->request) { case RADEON_INFO_DEVICE_ID: value = dev->pci_device; -- cgit v1.2.3 From 9695add7c48adc64e21428116249c59950a660bb Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 14 Aug 2010 21:08:48 +0200 Subject: hwmon: (pc87360) Fix device resource declaration commit b9783dcebe952bf73449fe70a19ee4814adc81a0 upstream. It's not OK to call platform_device_add_resources() multiple times in a row. Despite its name, this functions sets the resources, it doesn't add them. So we have to prepare an array with all the resources, and then call platform_device_add_resources() once. Before this fix, only the last I/O resource would be actually registered. The other I/O resources were leaked. Signed-off-by: Jean Delvare Cc: Jim Cromie Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/pc87360.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index 4a64b85d4ec9..68e69a49633c 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c @@ -1610,11 +1610,8 @@ static struct pc87360_data *pc87360_update_device(struct device *dev) static int __init pc87360_device_add(unsigned short address) { - struct resource res = { - .name = "pc87360", - .flags = IORESOURCE_IO, - }; - int err, i; + struct resource res[3]; + int err, i, res_count; pdev = platform_device_alloc("pc87360", address); if (!pdev) { @@ -1623,22 +1620,28 @@ static int __init pc87360_device_add(unsigned short address) goto exit; } + memset(res, 0, 3 * sizeof(struct resource)); + res_count = 0; for (i = 0; i < 3; i++) { if (!extra_isa[i]) continue; - res.start = extra_isa[i]; - res.end = extra_isa[i] + PC87360_EXTENT - 1; + res[res_count].start = extra_isa[i]; + res[res_count].end = extra_isa[i] + PC87360_EXTENT - 1; + res[res_count].name = "pc87360", + res[res_count].flags = IORESOURCE_IO, - err = acpi_check_resource_conflict(&res); + err = acpi_check_resource_conflict(&res[res_count]); if (err) goto exit_device_put; - err = platform_device_add_resources(pdev, &res, 1); - if (err) { - printk(KERN_ERR "pc87360: Device resource[%d] " - "addition failed (%d)\n", i, err); - goto exit_device_put; - } + res_count++; + } + + err = platform_device_add_resources(pdev, res, res_count); + if (err) { + printk(KERN_ERR "pc87360: Device resources addition failed " + "(%d)\n", err); + goto exit_device_put; } err = platform_device_add(pdev); -- cgit v1.2.3 From 01d74006e1d39fa2a94fd6fde5c141f65d4069f3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 13 Aug 2010 23:33:46 +0100 Subject: ARM: Tighten check for allowable CPSR values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 41e2e8fd34fff909a0e40129f6ac4233ecfa67a9 upstream. Reviewed-by: Arve Hjønnevåg Acked-by: Dima Zavin Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/ptrace.h | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 9dcb11e59026..bf62c449514e 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -158,15 +158,24 @@ struct pt_regs { */ static inline int valid_user_regs(struct pt_regs *regs) { - if (user_mode(regs) && (regs->ARM_cpsr & PSR_I_BIT) == 0) { - regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT); - return 1; + unsigned long mode = regs->ARM_cpsr & MODE_MASK; + + /* + * Always clear the F (FIQ) and A (delayed abort) bits + */ + regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT); + + if ((regs->ARM_cpsr & PSR_I_BIT) == 0) { + if (mode == USR_MODE) + return 1; + if (elf_hwcap & HWCAP_26BIT && mode == USR26_MODE) + return 1; } /* * Force CPSR to something logical... */ - regs->ARM_cpsr &= PSR_f | PSR_s | (PSR_x & ~PSR_A_BIT) | PSR_T_BIT | MODE32_BIT; + regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | PSR_T_BIT | MODE32_BIT; if (!(elf_hwcap & HWCAP_26BIT)) regs->ARM_cpsr |= USR_MODE; -- cgit v1.2.3 From 665de5aa85cd9a088f594733a4430d7faea92337 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 12 Aug 2010 02:14:54 +0100 Subject: ARM: Fix gen_nand probe structures contents commit ef077179a2909d3d0d3accf29ad1ea9ebb19019b upstream. These three platforms didn't properly fill nr_chips in gen_nand registration and therefore depended on gen_nand bug fixed by commit 81cbb0b17796d81cbd92defe113cf2a7c7a21fbb ("mtd: gen_nand: fix support for multiple chips") Signed-off-by: Marek Vasut Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-ixp4xx/ixdp425-setup.c | 1 + arch/arm/mach-mx3/mach-qong.c | 1 + arch/arm/mach-orion5x/ts78xx-setup.c | 1 + 3 files changed, 3 insertions(+) diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index 827cbc4402f4..ea9ee4ed0a3e 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -100,6 +100,7 @@ ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) static struct platform_nand_data ixdp425_flash_nand_data = { .chip = { + .nr_chips = 1, .chip_delay = 30, .options = NAND_NO_AUTOINCR, #ifdef CONFIG_MTD_PARTITIONS diff --git a/arch/arm/mach-mx3/mach-qong.c b/arch/arm/mach-mx3/mach-qong.c index e5b5b8323a17..1f9363fcd7b6 100644 --- a/arch/arm/mach-mx3/mach-qong.c +++ b/arch/arm/mach-mx3/mach-qong.c @@ -169,6 +169,7 @@ static void qong_nand_select_chip(struct mtd_info *mtd, int chip) static struct platform_nand_data qong_nand_data = { .chip = { + .nr_chips = 1, .chip_delay = 20, .options = 0, }, diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index 5041d1bc26b1..696b1a97f9e2 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@ -216,6 +216,7 @@ static struct mtd_partition ts78xx_ts_nand_parts[] = { static struct platform_nand_data ts78xx_ts_nand_data = { .chip = { + .nr_chips = 1, .part_probe_types = ts_nand_part_probes, .partitions = ts78xx_ts_nand_parts, .nr_partitions = ARRAY_SIZE(ts78xx_ts_nand_parts), -- cgit v1.2.3 From 6a7aa7194ab55f59bb70ab6b09374b3dc993edea Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 12 Aug 2010 03:53:54 +0100 Subject: BFIN: Fix gen_nand probe structures contents commit ef56609f9c7fdf5baa9d9f86f84a7bd8a717cd25 upstream. These two platforms didn't properly fill nr_chips in gen_nand registration and therefore depended on gen_nand bug fixed by by commit 81cbb0b17796d81cbd92defe113cf2a7c7a21fbb ("mtd: gen_nand: fix support for multiple chips") Signed-off-by: Marek Vasut Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- arch/blackfin/mach-bf537/boards/stamp.c | 1 + arch/blackfin/mach-bf561/boards/acvilon.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 9eaf5b05c11e..68a27bccc7d4 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -400,6 +400,7 @@ static int bfin_plat_nand_dev_ready(struct mtd_info *mtd) static struct platform_nand_data bfin_plat_nand_data = { .chip = { + .nr_chips = 1, .chip_delay = 30, #ifdef CONFIG_MTD_PARTITIONS .part_probe_types = part_probes, diff --git a/arch/blackfin/mach-bf561/boards/acvilon.c b/arch/blackfin/mach-bf561/boards/acvilon.c index bfcfa86db2b5..35b6d124c1e3 100644 --- a/arch/blackfin/mach-bf561/boards/acvilon.c +++ b/arch/blackfin/mach-bf561/boards/acvilon.c @@ -284,6 +284,7 @@ static int bfin_plat_nand_dev_ready(struct mtd_info *mtd) static struct platform_nand_data bfin_plat_nand_data = { .chip = { + .nr_chips = 1, .chip_delay = 30, #ifdef CONFIG_MTD_PARTITIONS .part_probe_types = part_probes, -- cgit v1.2.3 From b97ef8ac88b78b67616fa6da71889ba836b6f568 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Wed, 11 Aug 2010 20:27:43 +0530 Subject: ath9k_htc: fix panic on packet injection using airbase-ng tool. commit da93f10684bfba2983a70c10b5d417232b6a5245 upstream. This should fix the oops which occurs during the packet injection on monitor interface. EIP is at ath9k_htc_tx_start+0x69/0x220 [ath9k_htc] [] ? invoke_tx_handlers+0xa5a/0xee0 [mac80211] [] ? ath9k_htc_tx+0x44/0xe0 [ath9k_htc] [] ? __ieee80211_tx+0xf8/0x190 [mac80211] [] ? ieee80211_tx+0x9d/0x1a0 [mac80211] [] ? ieee80211_xmit+0x9c/0x1c0 [mac80211] [] ? ieee80211_monitor_start_xmit+0x85/0xb0 [mac80211] [] ? dev_hard_start_xmit+0x1ad/0x210 [] ? __alloc_skb+0x52/0x130 [] ? sch_direct_xmit+0x105/0x170 [] ? dev_queue_xmit+0x37f/0x4b0 [] ? packet_snd+0x21e/0x250 [] ? packet_sendmsg+0x32/0x40 [] ? sock_aio_write+0x113/0x130 [] ? do_sync_write+0xc4/0x100 [] ? autoremove_wake_function+0x0/0x50 [] ? security_file_permission+0x14/0x20 [] ? rw_verify_area+0x64/0xe0 [] ? handle_mm_fault+0x338/0x390 [] ? vfs_write+0x185/0x1a0 [] ? do_page_fault+0x160/0x3a0 [] ? sys_write+0x42/0x70 [] ? syscall_call+0x7/0xb Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 2571b443ac82..5fcbc2ff31ac 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -68,18 +68,23 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_sta *sta = tx_info->control.sta; struct ath9k_htc_sta *ista; - struct ath9k_htc_vif *avp; struct ath9k_htc_tx_ctl tx_ctl; enum htc_endpoint_id epid; u16 qnum, hw_qnum; __le16 fc; u8 *tx_fhdr; - u8 sta_idx; + u8 sta_idx, vif_idx; hdr = (struct ieee80211_hdr *) skb->data; fc = hdr->frame_control; - avp = (struct ath9k_htc_vif *) tx_info->control.vif->drv_priv; + if (tx_info->control.vif && + (struct ath9k_htc_vif *) tx_info->control.vif->drv_priv) + vif_idx = ((struct ath9k_htc_vif *) + tx_info->control.vif->drv_priv)->index; + else + vif_idx = priv->nvifs; + if (sta) { ista = (struct ath9k_htc_sta *) sta->drv_priv; sta_idx = ista->index; @@ -96,7 +101,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); tx_hdr.node_idx = sta_idx; - tx_hdr.vif_idx = avp->index; + tx_hdr.vif_idx = vif_idx; if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { tx_ctl.type = ATH9K_HTC_AMPDU; @@ -156,7 +161,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) tx_ctl.type = ATH9K_HTC_NORMAL; mgmt_hdr.node_idx = sta_idx; - mgmt_hdr.vif_idx = avp->index; + mgmt_hdr.vif_idx = vif_idx; mgmt_hdr.tidno = 0; mgmt_hdr.flags = 0; -- cgit v1.2.3 From 286ba0c3d1e5526a0d9600cec80f04d187465c2d Mon Sep 17 00:00:00 2001 From: "Patrick J. LoPresti" Date: Tue, 10 Aug 2010 17:28:01 -0400 Subject: nfs: Add "lookupcache" to displayed mount options commit 9b00c64318cc337846a7a08a5678f5f19aeff188 upstream. Running "cat /proc/mounts" fails to display the "lookupcache" option. This oversight cost me a bunch of wasted time recently. The following simple patch fixes it. Signed-off-by: Patrick LoPresti Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/super.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index f9df16de4a56..6bf11d745a3f 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -652,6 +652,13 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, if (nfss->options & NFS_OPTION_FSCACHE) seq_printf(m, ",fsc"); + + if (nfss->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG) { + if (nfss->flags & NFS_MOUNT_LOOKUP_CACHE_NONE) + seq_printf(m, ",lookupcache=none"); + else + seq_printf(m, ",lookupcache=pos"); + } } /* -- cgit v1.2.3 From 31e682b1a760001e14a5965ee1a3b0c582fbf125 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 18 Aug 2010 09:25:42 -0400 Subject: NFS: Fix an Oops in the NFSv4 atomic open code commit 0a377cff9428af2da2b293d11e07bc4dbf064ee5 upstream. Adam Lackorzynski reports: with 2.6.35.2 I'm getting this reproducible Oops: [ 110.825396] BUG: unable to handle kernel NULL pointer dereference at (null) [ 110.828638] IP: [] encode_attrs+0x1a/0x2a4 [ 110.828638] PGD be89f067 PUD bf18f067 PMD 0 [ 110.828638] Oops: 0000 [#1] SMP [ 110.828638] last sysfs file: /sys/class/net/lo/operstate [ 110.828638] CPU 2 [ 110.828638] Modules linked in: rtc_cmos rtc_core rtc_lib amd64_edac_mod i2c_amd756 edac_core i2c_core dm_mirror dm_region_hash dm_log dm_snapshot sg sr_mod usb_storage ohci_hcd mptspi tg3 mptscsih mptbase usbcore nls_base [last unloaded: scsi_wait_scan] [ 110.828638] [ 110.828638] Pid: 11264, comm: setchecksum Not tainted 2.6.35.2 #1 [ 110.828638] RIP: 0010:[] [] encode_attrs+0x1a/0x2a4 [ 110.828638] RSP: 0000:ffff88003bf5b878 EFLAGS: 00010296 [ 110.828638] RAX: ffff8800bddb48a8 RBX: ffff88003bf5bb18 RCX: 0000000000000000 [ 110.828638] RDX: ffff8800be258800 RSI: 0000000000000000 RDI: ffff88003bf5b9f8 [ 110.828638] RBP: 0000000000000000 R08: ffff8800bddb48a8 R09: 0000000000000004 [ 110.828638] R10: 0000000000000003 R11: ffff8800be779000 R12: ffff8800be258800 [ 110.828638] R13: ffff88003bf5b9f8 R14: ffff88003bf5bb20 R15: ffff8800be258800 [ 110.828638] FS: 0000000000000000(0000) GS:ffff880041e00000(0063) knlGS:00000000556bd6b0 [ 110.828638] CS: 0010 DS: 002b ES: 002b CR0: 000000008005003b [ 110.828638] CR2: 0000000000000000 CR3: 00000000be8ef000 CR4: 00000000000006e0 [ 110.828638] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 110.828638] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 110.828638] Process setchecksum (pid: 11264, threadinfo ffff88003bf5a000, task ffff88003f232210) [ 110.828638] Stack: [ 110.828638] 0000000000000000 ffff8800bfbcf920 0000000000000000 0000000000000ffe [ 110.828638] <0> 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [ 110.828638] <0> 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [ 110.828638] Call Trace: [ 110.828638] [] ? nfs4_xdr_enc_setattr+0x90/0xb4 [ 110.828638] [] ? call_transmit+0x1c3/0x24a [ 110.828638] [] ? __rpc_execute+0x78/0x22a [ 110.828638] [] ? rpc_run_task+0x21/0x2b [ 110.828638] [] ? rpc_call_sync+0x3d/0x5d [ 110.828638] [] ? _nfs4_do_setattr+0x11b/0x147 [ 110.828638] [] ? nfs_init_locked+0x0/0x32 [ 110.828638] [] ? ifind+0x4e/0x90 [ 110.828638] [] ? nfs4_do_setattr+0x4b/0x6e [ 110.828638] [] ? nfs4_do_open+0x291/0x3a6 [ 110.828638] [] ? nfs4_open_revalidate+0x63/0x14a [ 110.828638] [] ? nfs_open_revalidate+0xd7/0x161 [ 110.828638] [] ? do_lookup+0x1a4/0x201 [ 110.828638] [] ? link_path_walk+0x6a/0x9d5 [ 110.828638] [] ? do_last+0x17b/0x58e [ 110.828638] [] ? do_filp_open+0x1bd/0x56e [ 110.828638] [] ? _atomic_dec_and_lock+0x30/0x48 [ 110.828638] [] ? dput+0x37/0x152 [ 110.828638] [] ? alloc_fd+0x69/0x10a [ 110.828638] [] ? do_sys_open+0x56/0x100 [ 110.828638] [] ? ia32_sysret+0x0/0x5 [ 110.828638] Code: 83 f1 01 e8 f5 ca ff ff 48 83 c4 50 5b 5d 41 5c c3 41 57 41 56 41 55 49 89 fd 41 54 49 89 d4 55 48 89 f5 53 48 81 ec 18 01 00 00 <8b> 06 89 c2 83 e2 08 83 fa 01 19 db 83 e3 f8 83 c3 18 a8 01 8d [ 110.828638] RIP [] encode_attrs+0x1a/0x2a4 [ 110.828638] RSP [ 110.828638] CR2: 0000000000000000 [ 112.840396] ---[ end trace 95282e83fd77358f ]--- We need to ensure that the O_EXCL flag is turned off if the user doesn't set O_CREAT. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/dir.c | 2 +- fs/nfs/nfs4proc.c | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e60416d3f818..d69551e77b93 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1103,7 +1103,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) goto no_open_dput; /* We can't create new files, or truncate existing ones here */ - openflags &= ~(O_CREAT|O_TRUNC); + openflags &= ~(O_CREAT|O_EXCL|O_TRUNC); /* * Note: we're not holding inode->i_mutex and so may be racing with diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 70015dd60a98..330a3c9a1a03 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2023,7 +2023,8 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) struct rpc_cred *cred; struct nfs4_state *state; struct dentry *res; - fmode_t fmode = nd->intent.open.flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC); + int open_flags = nd->intent.open.flags; + fmode_t fmode = open_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC); if (nd->flags & LOOKUP_CREATE) { attr.ia_mode = nd->intent.open.create_mode; @@ -2031,8 +2032,9 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) if (!IS_POSIXACL(dir)) attr.ia_mode &= ~current_umask(); } else { + open_flags &= ~O_EXCL; attr.ia_valid = 0; - BUG_ON(nd->intent.open.flags & O_CREAT); + BUG_ON(open_flags & O_CREAT); } cred = rpc_lookup_cred(); @@ -2041,7 +2043,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) parent = dentry->d_parent; /* Protect against concurrent sillydeletes */ nfs_block_sillyrename(parent); - state = nfs4_do_open(dir, &path, fmode, nd->intent.open.flags, &attr, cred); + state = nfs4_do_open(dir, &path, fmode, open_flags, &attr, cred); put_rpccred(cred); if (IS_ERR(state)) { if (PTR_ERR(state) == -ENOENT) { -- cgit v1.2.3 From 18626abccb42a19a3bd6693cd5c4904d594b6c69 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Fri, 13 Aug 2010 11:27:28 -0400 Subject: ath5k: disable ASPM L0s for all cards commit 6ccf15a1a76d2ff915cdef6ae4d12d0170087118 upstream. Atheros PCIe wireless cards handled by ath5k do require L0s disabled. For distributions shipping with CONFIG_PCIEASPM (this will be enabled by default in the future in 2.6.36) this will also mean both L1 and L0s will be disabled when a pre 1.1 PCIe device is detected. We do know L1 works correctly even for all ath5k pre 1.1 PCIe devices though but cannot currently undue the effect of a blacklist, for details you can read pcie_aspm_sanity_check() and see how it adjusts the device link capability. It may be possible in the future to implement some PCI API to allow drivers to override blacklists for pre 1.1 PCIe but for now it is best to accept that both L0s and L1 will be disabled completely for distributions shipping with CONFIG_PCIEASPM rather than having this issue present. Motivation for adding this new API will be to help with power consumption for some of these devices. Example of issues you'd see: - On the Acer Aspire One (AOA150, Atheros Communications Inc. AR5001 Wireless Network Adapter [168c:001c] (rev 01)) doesn't work well with ASPM enabled, the card will eventually stall on heavy traffic with often 'unsupported jumbo' warnings appearing. Disabling ASPM L0s in ath5k fixes these problems. - On the same card you would see a storm of RXORN interrupts even though medium is idle. Credit for root causing and fixing the bug goes to Jussi Kivilinna. Cc: David Quan Cc: Matthew Garrett Cc: Tim Gardner Cc: Jussi Kivilinna Signed-off-by: Luis R. Rodriguez Signed-off-by: Maxim Levitsky Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath5k/base.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 648972df369d..ab9fe22e4dc5 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -472,6 +473,26 @@ ath5k_pci_probe(struct pci_dev *pdev, int ret; u8 csz; + /* + * L0s needs to be disabled on all ath5k cards. + * + * For distributions shipping with CONFIG_PCIEASPM (this will be enabled + * by default in the future in 2.6.36) this will also mean both L1 and + * L0s will be disabled when a pre 1.1 PCIe device is detected. We do + * know L1 works correctly even for all ath5k pre 1.1 PCIe devices + * though but cannot currently undue the effect of a blacklist, for + * details you can read pcie_aspm_sanity_check() and see how it adjusts + * the device link capability. + * + * It may be possible in the future to implement some PCI API to allow + * drivers to override blacklists for pre 1.1 PCIe but for now it is + * best to accept that both L0s and L1 will be disabled completely for + * distributions shipping with CONFIG_PCIEASPM rather than having this + * issue present. Motivation for adding this new API will be to help + * with power consumption for some of these devices. + */ + pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); + ret = pci_enable_device(pdev); if (ret) { dev_err(&pdev->dev, "can't enable device\n"); -- cgit v1.2.3 From f50b2280832c249cdd0829e98be5b7eec8f55afc Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 16 Aug 2010 16:09:09 +0800 Subject: pxa3xx: fix ns2cycle equation commit 93b352fce679945845664b56b0c3afbd655a7a12 upstream. Test on a PXA310 platform with Samsung K9F2G08X0B NAND flash, with tCH=5 and clk is 156MHz, ns2cycle(5, 156000000) returns -1. ns2cycle returns negtive value will break NDTR0_tXX macros. After checking the commit log, I found the problem is introduced by commit 5b0d4d7c8a67c5ba3d35e6ceb0c5530cc6846db7 "[MTD] [NAND] pxa3xx: convert from ns to clock ticks more accurately" To get num of clock cycles, we use below equation: num of clock cycles = time (ns) / one clock cycle (ns) + 1 We need to add 1 cycle here because integer division will truncate the result. It is possible the developers set the Min values in SPEC for timing settings. Thus the truncate may cause problem, and it is safe to add an extra cycle here. The various fields in NDTR{01} are in units of clock ticks minus one, thus we should subtract 1 cycle then. Thus the correct equation should be: num of clock cycles = time (ns) / one clock cycle (ns) + 1 - 1 = time (ns) / one clock cycle (ns) Signed-off-by: Axel Lin Signed-off-by: Lei Wen Acked-by: Eric Miao Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/pxa3xx_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index e02fa4f0e3c9..4d89f3780207 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -363,7 +363,7 @@ static struct pxa3xx_nand_flash *builtin_flash_types[] = { #define tAR_NDTR1(r) (((r) >> 0) & 0xf) /* convert nano-seconds to nand flash controller clock cycles */ -#define ns2cycle(ns, clk) (int)(((ns) * (clk / 1000000) / 1000) - 1) +#define ns2cycle(ns, clk) (int)((ns) * (clk / 1000000) / 1000) /* convert nand flash controller clock cycles to nano-seconds */ #define cycle2ns(c, clk) ((((c) + 1) * 1000000 + clk / 500) / (clk / 1000)) -- cgit v1.2.3 From e5c9bc34a675a7f9d88c63fd63815a531306a36e Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Thu, 19 Aug 2010 14:13:25 -0700 Subject: matroxfb: fix incorrect use of memcpy_toio() commit c81476df1b4241aefba4ff83a7701b3a926bd7ce upstream. Screen is completely corrupted since 2.6.34. Bisection revealed that it's caused by commit 6175ddf06b61720 ("x86: Clean up mem*io functions."). H. Peter Anvin explained that memcpy_toio() does not copy data in 32bit chunks anymore on x86. Signed-off-by: Ondrej Zary Cc: Brian Gerst Cc: H. Peter Anvin Cc: Petr Vandrovec Cc: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/video/matrox/matroxfb_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index f3a4e15672d9..f96a471cb1a8 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -151,13 +151,13 @@ static inline void mga_writel(vaddr_t va, unsigned int offs, u_int32_t value) { static inline void mga_memcpy_toio(vaddr_t va, const void* src, int len) { #if defined(__alpha__) || defined(__i386__) || defined(__x86_64__) /* - * memcpy_toio works for us if: + * iowrite32_rep works for us if: * (1) Copies data as 32bit quantities, not byte after byte, * (2) Performs LE ordered stores, and * (3) It copes with unaligned source (destination is guaranteed to be page * aligned and length is guaranteed to be multiple of 4). */ - memcpy_toio(va.vaddr, src, len); + iowrite32_rep(va.vaddr, src, len >> 2); #else u_int32_t __iomem* addr = va.vaddr; -- cgit v1.2.3 From 01be8ecc0e14a6c3478088f73cdaf2008d1dbdec Mon Sep 17 00:00:00 2001 From: Tilman Sauerbeck Date: Fri, 20 Aug 2010 14:01:47 -0700 Subject: mtd: nand: Fix probe of Samsung NAND chips commit cfe3fdadb16162327773ef01a575a32000b8c7f4 upstream. Apparently, the check for a 6-byte ID string introduced by commit 426c457a3216fac74e3d44dd39729b0689f4c7ab ("mtd: nand: extend NAND flash detection to new MLC chips") is NOT sufficient to determine whether or not a Samsung chip uses their new MLC detection scheme or the old, standard scheme. This adds a condition to check cell type. Signed-off-by: Tilman Sauerbeck Signed-off-by: Brian Norris Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/nand_base.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 4a7b86423ee9..5bcc34a51150 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2852,6 +2852,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, */ if (id_data[0] == id_data[6] && id_data[1] == id_data[7] && id_data[0] == NAND_MFR_SAMSUNG && + (chip->cellinfo & NAND_CI_CELLTYPE_MSK) && id_data[5] != 0x00) { /* Calc pagesize */ mtd->writesize = 2048 << (extid & 0x03); -- cgit v1.2.3 From 6eb22281116bd7eea73f63884b74b3c0aca0a5d3 Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Thu, 5 Aug 2010 09:19:26 +0200 Subject: mtd: change struct flchip_shared spinlock locking into mutex commit 8ae664184c45def51ff0b61d4bd6c6671db6cb4f upstream. This patch prevent to schedule while atomic by changing the flchip_shared spinlock into a mutex. This should be save since no atomic path will use this lock. It was suggested by Arnd Bergmann and Vasiliy Kulikov. Signed-off-by: Stefani Seibold Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/chips/cfi_cmdset_0001.c | 20 ++++++++++---------- drivers/mtd/lpddr/lpddr_cmds.c | 20 ++++++++++---------- include/linux/mtd/flashchip.h | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 62f3ea9de848..33640614c51a 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -717,7 +717,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, chip = &newcfi->chips[0]; for (i = 0; i < cfi->numchips; i++) { shared[i].writing = shared[i].erasing = NULL; - spin_lock_init(&shared[i].lock); + mutex_init(&shared[i].lock); for (j = 0; j < numparts; j++) { *chip = cfi->chips[i]; chip->start += j << partshift; @@ -886,7 +886,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr */ struct flchip_shared *shared = chip->priv; struct flchip *contender; - spin_lock(&shared->lock); + mutex_lock(&shared->lock); contender = shared->writing; if (contender && contender != chip) { /* @@ -899,7 +899,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr * get_chip returns success we're clear to go ahead. */ ret = mutex_trylock(&contender->mutex); - spin_unlock(&shared->lock); + mutex_unlock(&shared->lock); if (!ret) goto retry; mutex_unlock(&chip->mutex); @@ -914,7 +914,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr mutex_unlock(&contender->mutex); return ret; } - spin_lock(&shared->lock); + mutex_lock(&shared->lock); /* We should not own chip if it is already * in FL_SYNCING state. Put contender and retry. */ @@ -930,7 +930,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr * on this chip. Sleep. */ if (mode == FL_ERASING && shared->erasing && shared->erasing->oldstate == FL_ERASING) { - spin_unlock(&shared->lock); + mutex_unlock(&shared->lock); set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&chip->wq, &wait); mutex_unlock(&chip->mutex); @@ -944,7 +944,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr shared->writing = chip; if (mode == FL_ERASING) shared->erasing = chip; - spin_unlock(&shared->lock); + mutex_unlock(&shared->lock); } ret = chip_ready(map, chip, adr, mode); if (ret == -EAGAIN) @@ -959,7 +959,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad if (chip->priv) { struct flchip_shared *shared = chip->priv; - spin_lock(&shared->lock); + mutex_lock(&shared->lock); if (shared->writing == chip && chip->oldstate == FL_READY) { /* We own the ability to write, but we're done */ shared->writing = shared->erasing; @@ -967,7 +967,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad /* give back ownership to who we loaned it from */ struct flchip *loaner = shared->writing; mutex_lock(&loaner->mutex); - spin_unlock(&shared->lock); + mutex_unlock(&shared->lock); mutex_unlock(&chip->mutex); put_chip(map, loaner, loaner->start); mutex_lock(&chip->mutex); @@ -985,11 +985,11 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad * Don't let the switch below mess things up since * we don't have ownership to resume anything. */ - spin_unlock(&shared->lock); + mutex_unlock(&shared->lock); wake_up(&chip->wq); return; } - spin_unlock(&shared->lock); + mutex_unlock(&shared->lock); } switch(chip->oldstate) { diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c index fece5be58715..04fdfcca93f7 100644 --- a/drivers/mtd/lpddr/lpddr_cmds.c +++ b/drivers/mtd/lpddr/lpddr_cmds.c @@ -98,7 +98,7 @@ struct mtd_info *lpddr_cmdset(struct map_info *map) numchips = lpddr->numchips / lpddr->qinfo->HWPartsNum; for (i = 0; i < numchips; i++) { shared[i].writing = shared[i].erasing = NULL; - spin_lock_init(&shared[i].lock); + mutex_init(&shared[i].lock); for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) { *chip = lpddr->chips[i]; chip->start += j << lpddr->chipshift; @@ -217,7 +217,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) */ struct flchip_shared *shared = chip->priv; struct flchip *contender; - spin_lock(&shared->lock); + mutex_lock(&shared->lock); contender = shared->writing; if (contender && contender != chip) { /* @@ -230,7 +230,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) * get_chip returns success we're clear to go ahead. */ ret = mutex_trylock(&contender->mutex); - spin_unlock(&shared->lock); + mutex_unlock(&shared->lock); if (!ret) goto retry; mutex_unlock(&chip->mutex); @@ -245,7 +245,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) mutex_unlock(&contender->mutex); return ret; } - spin_lock(&shared->lock); + mutex_lock(&shared->lock); /* We should not own chip if it is already in FL_SYNCING * state. Put contender and retry. */ @@ -261,7 +261,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) Must sleep in such a case. */ if (mode == FL_ERASING && shared->erasing && shared->erasing->oldstate == FL_ERASING) { - spin_unlock(&shared->lock); + mutex_unlock(&shared->lock); set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&chip->wq, &wait); mutex_unlock(&chip->mutex); @@ -275,7 +275,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) shared->writing = chip; if (mode == FL_ERASING) shared->erasing = chip; - spin_unlock(&shared->lock); + mutex_unlock(&shared->lock); } ret = chip_ready(map, chip, mode); @@ -348,7 +348,7 @@ static void put_chip(struct map_info *map, struct flchip *chip) { if (chip->priv) { struct flchip_shared *shared = chip->priv; - spin_lock(&shared->lock); + mutex_lock(&shared->lock); if (shared->writing == chip && chip->oldstate == FL_READY) { /* We own the ability to write, but we're done */ shared->writing = shared->erasing; @@ -356,7 +356,7 @@ static void put_chip(struct map_info *map, struct flchip *chip) /* give back the ownership */ struct flchip *loaner = shared->writing; mutex_lock(&loaner->mutex); - spin_unlock(&shared->lock); + mutex_unlock(&shared->lock); mutex_unlock(&chip->mutex); put_chip(map, loaner); mutex_lock(&chip->mutex); @@ -374,11 +374,11 @@ static void put_chip(struct map_info *map, struct flchip *chip) * Don't let the switch below mess things up since * we don't have ownership to resume anything. */ - spin_unlock(&shared->lock); + mutex_unlock(&shared->lock); wake_up(&chip->wq); return; } - spin_unlock(&shared->lock); + mutex_unlock(&shared->lock); } switch (chip->oldstate) { diff --git a/include/linux/mtd/flashchip.h b/include/linux/mtd/flashchip.h index f43e9b49b751..23cc10f8e343 100644 --- a/include/linux/mtd/flashchip.h +++ b/include/linux/mtd/flashchip.h @@ -92,7 +92,7 @@ struct flchip { /* This is used to handle contention on write/erase operations between partitions of the same physical chip. */ struct flchip_shared { - spinlock_t lock; + struct mutex lock; struct flchip *writing; struct flchip *erasing; }; -- cgit v1.2.3 From aa6b6a4b1b48e26b95af02eee80c8741eb2a4684 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 4 Aug 2010 21:22:09 +0200 Subject: drm/i915: fixup pageflip ringbuffer commands for i8xx commit 69d0b96c095468526009cb3104eee561c9252a84 upstream. Add a new path for 2nd gen chips that uses the commands for i81x chips (where public docs do exist) augmented with the plane bits from i915. It seems to work and doesn't result in a black screen like before. Signed-off-by: Daniel Vetter [anholt: resolved against conflict] Reviewed-by: Jesse Barnes Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8a84306292e0..a2f7f3c12311 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4837,12 +4837,18 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, OUT_RING(offset | obj_priv->tiling_mode); pipesrc = I915_READ(pipesrc_reg); OUT_RING(pipesrc & 0x0fff0fff); - } else { + } else if (IS_GEN3(dev)) { OUT_RING(MI_DISPLAY_FLIP_I915 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); OUT_RING(fb->pitch); OUT_RING(offset); OUT_RING(MI_NOOP); + } else { + OUT_RING(MI_DISPLAY_FLIP | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + OUT_RING(fb->pitch); + OUT_RING(offset); + OUT_RING(MI_NOOP); } ADVANCE_LP_RING(); -- cgit v1.2.3 From 8a8c25a716100dc9a50e5546fadf03e56588ee09 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 4 Aug 2010 21:22:10 +0200 Subject: drm/i915: i8xx also doesn't like multiple oustanding pageflips commit 6146b3d61925116e3fecce36c2fd873665bd6614 upstream. My i855GM suffers from a 80k/s interrupt storm without this. So add 2nd gen to the list of things that don't like more than one outstanding pageflip request. Furthermore I've changed the busy loop into a ringbuffer wait. Busy-loops that don't check whether the chip died are simply evil. And performance should actually improve, because there's usually a decent amount of rendering queued on the gpu, hopefully rendering that MI_WAIT into a noop by the time it's executed. The current code holds dev->struct_mutex while executing this loop, hence stalling all other gem activity anyway. Signed-off-by: Daniel Vetter Reviewed-by: Jesse Barnes [anholt: resolved against conflict] Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a2f7f3c12311..0a552c884e4b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4816,14 +4816,16 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, work->pending_flip_obj = obj; if (intel_crtc->plane) - flip_mask = I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT; + flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; else - flip_mask = I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT; + flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; - /* Wait for any previous flip to finish */ - if (IS_GEN3(dev)) - while (I915_READ(ISR) & flip_mask) - ; + if (IS_GEN3(dev) || IS_GEN2(dev)) { + BEGIN_LP_RING(2); + OUT_RING(MI_WAIT_FOR_EVENT | flip_mask); + OUT_RING(0); + ADVANCE_LP_RING(); + } /* Offset into the new buffer for cases of shared fbs between CRTCs */ offset = obj_priv->gtt_offset; -- cgit v1.2.3 From 4f2624fb7b37bf8d8b36bb01e2e86939ca049dbc Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 7 Aug 2010 11:01:36 +0100 Subject: drm/i915/edp: Flush the write before waiting for PLLs commit 5ddb954b9ee50824977d2931e0ff58b3050b337d upstream. Signed-off-by: Chris Wilson Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0a552c884e4b..e9a4b125d66e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1502,6 +1502,7 @@ static void ironlake_enable_pll_edp (struct drm_crtc *crtc) dpa_ctl = I915_READ(DP_A); dpa_ctl |= DP_PLL_ENABLE; I915_WRITE(DP_A, dpa_ctl); + POSTING_READ(DP_A); udelay(200); } -- cgit v1.2.3 From 72c7a360cd31bef331571fcca735adbeffb250d5 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 12 Aug 2010 04:13:50 +0100 Subject: dm snapshot: iterate origin and cow devices commit 1e5554c8428bc7209a83e2d07ca724be4d981ce3 upstream. Iterate both origin and snapshot devices iterate_devices method should call the callback for all the devices where the bio may be remapped. Thus, snapshot_iterate_devices should call the callback for both snapshot and origin underlying devices because it remaps some bios to the snapshot and some to the origin. snapshot_iterate_devices called the callback only for the origin device. This led to badly calculated device limits if snapshot and origin were placed on different types of disks. Signed-off-by: Mikulas Patocka Reviewed-by: Mike Snitzer Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-snap.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 54853773510c..a6ab98920cc3 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -1899,8 +1899,14 @@ static int snapshot_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data) { struct dm_snapshot *snap = ti->private; + int r; + + r = fn(ti, snap->origin, 0, ti->len, data); - return fn(ti, snap->origin, 0, ti->len, data); + if (!r) + r = fn(ti, snap->cow, 0, get_dev_size(snap->cow->bdev), data); + + return r; } -- cgit v1.2.3 From d59e0c5a9314ff7d6daf93c3aa680c549d267e46 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 12 Aug 2010 04:13:51 +0100 Subject: dm snapshot: test chunk size against both origin and snapshot commit c24110450650f17f7d3ba4fbe01f01ac5a115456 upstream. Validate chunk size against both origin and snapshot sector size Don't allow chunk size smaller than either origin or snapshot logical sector size. Reading or writing data not aligned to sector size is not allowed and causes immediate errors. This requires us to open the origin before initialising the exception store and to export dm_snap_origin. Signed-off-by: Mikulas Patocka Reviewed-by: Mike Snitzer Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-exception-store.c | 4 +++- drivers/md/dm-exception-store.h | 3 ++- drivers/md/dm-snap.c | 36 +++++++++++++++++++++--------------- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index 2b7907b6dd09..0bdb201c2c2a 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c @@ -173,7 +173,9 @@ int dm_exception_store_set_chunk_size(struct dm_exception_store *store, /* Validate the chunk size against the device block size */ if (chunk_size % - (bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9)) { + (bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9) || + chunk_size % + (bdev_logical_block_size(dm_snap_origin(store->snap)->bdev) >> 9)) { *error = "Chunk size is not a multiple of device blocksize"; return -EINVAL; } diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h index e8dfa06af3ba..0b2536247cf5 100644 --- a/drivers/md/dm-exception-store.h +++ b/drivers/md/dm-exception-store.h @@ -126,8 +126,9 @@ struct dm_exception_store { }; /* - * Obtain the cow device used by a given snapshot. + * Obtain the origin or cow device used by a given snapshot. */ +struct dm_dev *dm_snap_origin(struct dm_snapshot *snap); struct dm_dev *dm_snap_cow(struct dm_snapshot *snap); /* diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index a6ab98920cc3..a1f2ab553b92 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -148,6 +148,12 @@ struct dm_snapshot { #define RUNNING_MERGE 0 #define SHUTDOWN_MERGE 1 +struct dm_dev *dm_snap_origin(struct dm_snapshot *s) +{ + return s->origin; +} +EXPORT_SYMBOL(dm_snap_origin); + struct dm_dev *dm_snap_cow(struct dm_snapshot *s) { return s->cow; @@ -1065,10 +1071,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) origin_mode = FMODE_WRITE; } - origin_path = argv[0]; - argv++; - argc--; - s = kmalloc(sizeof(*s), GFP_KERNEL); if (!s) { ti->error = "Cannot allocate snapshot context private " @@ -1077,6 +1079,16 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad; } + origin_path = argv[0]; + argv++; + argc--; + + r = dm_get_device(ti, origin_path, origin_mode, &s->origin); + if (r) { + ti->error = "Cannot get origin device"; + goto bad_origin; + } + cow_path = argv[0]; argv++; argc--; @@ -1097,12 +1109,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) argv += args_used; argc -= args_used; - r = dm_get_device(ti, origin_path, origin_mode, &s->origin); - if (r) { - ti->error = "Cannot get origin device"; - goto bad_origin; - } - s->ti = ti; s->valid = 1; s->active = 0; @@ -1212,15 +1218,15 @@ bad_kcopyd: dm_exception_table_exit(&s->complete, exception_cache); bad_hash_tables: - dm_put_device(ti, s->origin); - -bad_origin: dm_exception_store_destroy(s->store); bad_store: dm_put_device(ti, s->cow); bad_cow: + dm_put_device(ti, s->origin); + +bad_origin: kfree(s); bad: @@ -1314,12 +1320,12 @@ static void snapshot_dtr(struct dm_target *ti) mempool_destroy(s->pending_pool); - dm_put_device(ti, s->origin); - dm_exception_store_destroy(s->store); dm_put_device(ti, s->cow); + dm_put_device(ti, s->origin); + kfree(s); } -- cgit v1.2.3 From c51ca7940efce22c43da532c6ff5b36c7cb3ea5e Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Thu, 12 Aug 2010 04:13:54 +0100 Subject: dm: prevent access to md being deleted commit abdc568b0540bec6d3e0afebac496adef1189b77 upstream. This patch prevents access to mapped_device which is being deleted. Currently, even after a mapped_device has been removed from the hash, it could be accessed through idr_find() using minor number. That could cause a race and NULL pointer reference below: CPU0 CPU1 ------------------------------------------------------------------ dev_remove(param) down_write(_hash_lock) dm_lock_for_deletion(md) spin_lock(_minor_lock) set_bit(DMF_DELETING) spin_unlock(_minor_lock) __hash_remove(hc) up_write(_hash_lock) dev_status(param) md = find_device(param) down_read(_hash_lock) __find_device_hash_cell(param) dm_get_md(param->dev) md = dm_find_md(dev) spin_lock(_minor_lock) md = idr_find(MINOR(dev)) spin_unlock(_minor_lock) dm_put(md) free_dev(md) dm_get(md) up_read(_hash_lock) __dev_status(md, param) dm_put(md) This patch fixes such problems. Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index d21e1284604f..56d192dbe9f1 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -2141,6 +2141,7 @@ static struct mapped_device *dm_find_md(dev_t dev) md = idr_find(&_minor_idr, minor); if (md && (md == MINOR_ALLOCED || (MINOR(disk_devt(dm_disk(md))) != minor) || + dm_deleting_md(md) || test_bit(DMF_FREEING, &md->flags))) { md = NULL; goto out; -- cgit v1.2.3 From d97eabc0a58382629c2ed4f406259ad615fcbc88 Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Thu, 12 Aug 2010 04:13:55 +0100 Subject: dm ioctl: release _hash_lock between devices in remove_all commit 98f332855effef02aeb738e4d62e9a5b903c52fd upstream. This patch changes dm_hash_remove_all() to release _hash_lock when removing a device. After removing the device, dm_hash_remove_all() takes _hash_lock and searches the hash from scratch again. This patch is a preparation for the next patch, which changes device deletion code to wait for md reference to be 0. Without this patch, the wait in the next patch may cause AB-BA deadlock: CPU0 CPU1 ----------------------------------------------------------------------- dm_hash_remove_all() down_write(_hash_lock) table_status() md = find_device() dm_get(md) holders> dm_get_live_or_inactive_table() dm_get_inactive_table() down_write(_hash_lock) holders to be 0> Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-ioctl.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index d7500e1c26f2..f81c53604141 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -249,40 +249,46 @@ static void __hash_remove(struct hash_cell *hc) static void dm_hash_remove_all(int keep_open_devices) { - int i, dev_skipped, dev_removed; + int i, dev_skipped; struct hash_cell *hc; - struct list_head *tmp, *n; + struct mapped_device *md; + +retry: + dev_skipped = 0; down_write(&_hash_lock); -retry: - dev_skipped = dev_removed = 0; for (i = 0; i < NUM_BUCKETS; i++) { - list_for_each_safe (tmp, n, _name_buckets + i) { - hc = list_entry(tmp, struct hash_cell, name_list); + list_for_each_entry(hc, _name_buckets + i, name_list) { + md = hc->md; + dm_get(md); - if (keep_open_devices && - dm_lock_for_deletion(hc->md)) { + if (keep_open_devices && dm_lock_for_deletion(md)) { + dm_put(md); dev_skipped++; continue; } + __hash_remove(hc); - dev_removed = 1; - } - } - /* - * Some mapped devices may be using other mapped devices, so if any - * still exist, repeat until we make no further progress. - */ - if (dev_skipped) { - if (dev_removed) - goto retry; + up_write(&_hash_lock); - DMWARN("remove_all left %d open device(s)", dev_skipped); + dm_put(md); + + /* + * Some mapped devices may be using other mapped + * devices, so repeat until we make no further + * progress. If a new mapped device is created + * here it will also get removed. + */ + goto retry; + } } up_write(&_hash_lock); + + if (dev_skipped) + DMWARN("remove_all left %d open device(s)", dev_skipped); } static int dm_hash_rename(uint32_t cookie, uint32_t *flags, const char *old, -- cgit v1.2.3 From f5981434834ad0373b8fc58deabf6493564ae42a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 20 Aug 2010 16:24:55 -0700 Subject: mm: make the vma list be doubly linked commit 297c5eee372478fc32fec5fe8eed711eedb13f3d upstream. It's a really simple list, and several of the users want to go backwards in it to find the previous vma. So rather than have to look up the previous entry with 'find_vma_prev()' or something similar, just make it doubly linked instead. Tested-by: Ian Campbell Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/mm_types.h | 2 +- kernel/fork.c | 7 +++++-- mm/mmap.c | 21 +++++++++++++++++---- mm/nommu.c | 7 +++++-- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index b8bb9a6a1f37..ee7e258627f9 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -134,7 +134,7 @@ struct vm_area_struct { within vm_mm. */ /* linked list of VM areas per task, sorted by address */ - struct vm_area_struct *vm_next; + struct vm_area_struct *vm_next, *vm_prev; pgprot_t vm_page_prot; /* Access permissions of this VMA. */ unsigned long vm_flags; /* Flags, see mm.h. */ diff --git a/kernel/fork.c b/kernel/fork.c index b6cce14ba047..e96c0cd67e4a 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -300,7 +300,7 @@ out: #ifdef CONFIG_MMU static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) { - struct vm_area_struct *mpnt, *tmp, **pprev; + struct vm_area_struct *mpnt, *tmp, *prev, **pprev; struct rb_node **rb_link, *rb_parent; int retval; unsigned long charge; @@ -328,6 +328,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) if (retval) goto out; + prev = NULL; for (mpnt = oldmm->mmap; mpnt; mpnt = mpnt->vm_next) { struct file *file; @@ -359,7 +360,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) goto fail_nomem_anon_vma_fork; tmp->vm_flags &= ~VM_LOCKED; tmp->vm_mm = mm; - tmp->vm_next = NULL; + tmp->vm_next = tmp->vm_prev = NULL; file = tmp->vm_file; if (file) { struct inode *inode = file->f_path.dentry->d_inode; @@ -392,6 +393,8 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) */ *pprev = tmp; pprev = &tmp->vm_next; + tmp->vm_prev = prev; + prev = tmp; __vma_link_rb(mm, tmp, rb_link, rb_parent); rb_link = &tmp->vm_rb.rb_right; diff --git a/mm/mmap.c b/mm/mmap.c index 456ec6f27889..3867cfc21cc7 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -388,17 +388,23 @@ static inline void __vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev, struct rb_node *rb_parent) { + struct vm_area_struct *next; + + vma->vm_prev = prev; if (prev) { - vma->vm_next = prev->vm_next; + next = prev->vm_next; prev->vm_next = vma; } else { mm->mmap = vma; if (rb_parent) - vma->vm_next = rb_entry(rb_parent, + next = rb_entry(rb_parent, struct vm_area_struct, vm_rb); else - vma->vm_next = NULL; + next = NULL; } + vma->vm_next = next; + if (next) + next->vm_prev = vma; } void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma, @@ -485,7 +491,11 @@ static inline void __vma_unlink(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev) { - prev->vm_next = vma->vm_next; + struct vm_area_struct *next = vma->vm_next; + + prev->vm_next = next; + if (next) + next->vm_prev = prev; rb_erase(&vma->vm_rb, &mm->mm_rb); if (mm->mmap_cache == vma) mm->mmap_cache = prev; @@ -1900,6 +1910,7 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr; insertion_point = (prev ? &prev->vm_next : &mm->mmap); + vma->vm_prev = NULL; do { rb_erase(&vma->vm_rb, &mm->mm_rb); mm->map_count--; @@ -1907,6 +1918,8 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, vma = vma->vm_next; } while (vma && vma->vm_start < end); *insertion_point = vma; + if (vma) + vma->vm_prev = prev; tail_vma->vm_next = NULL; if (mm->unmap_area == arch_unmap_area) addr = prev ? prev->vm_end : mm->mmap_base; diff --git a/mm/nommu.c b/mm/nommu.c index b76f3ee0abe0..e48b38c521e4 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -609,7 +609,7 @@ static void protect_vma(struct vm_area_struct *vma, unsigned long flags) */ static void add_vma_to_mm(struct mm_struct *mm, struct vm_area_struct *vma) { - struct vm_area_struct *pvma, **pp; + struct vm_area_struct *pvma, **pp, *next; struct address_space *mapping; struct rb_node **p, *parent; @@ -669,8 +669,11 @@ static void add_vma_to_mm(struct mm_struct *mm, struct vm_area_struct *vma) break; } - vma->vm_next = *pp; + next = *pp; *pp = vma; + vma->vm_next = next; + if (next) + next->vm_prev = vma; } /* -- cgit v1.2.3 From e89cfc48a21fa83088e083fe6341ff803ab32f8e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 20 Aug 2010 16:39:25 -0700 Subject: mm: make the mlock() stack guard page checks stricter commit 7798330ac8114c731cfab83e634c6ecedaa233d7 upstream. If we've split the stack vma, only the lowest one has the guard page. Now that we have a doubly linked list of vma's, checking this is trivial. Tested-by: Ian Campbell Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mlock.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/mm/mlock.c b/mm/mlock.c index 49e5e4cb8232..cbae7c5b9568 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -135,6 +135,19 @@ void munlock_vma_page(struct page *page) } } +/* Is the vma a continuation of the stack vma above it? */ +static inline int vma_stack_continue(struct vm_area_struct *vma, unsigned long addr) +{ + return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN); +} + +static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr) +{ + return (vma->vm_flags & VM_GROWSDOWN) && + (vma->vm_start == addr) && + !vma_stack_continue(vma->vm_prev, addr); +} + /** * __mlock_vma_pages_range() - mlock a range of pages in the vma. * @vma: target vma @@ -168,11 +181,9 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma, gup_flags |= FOLL_WRITE; /* We don't try to access the guard page of a stack vma */ - if (vma->vm_flags & VM_GROWSDOWN) { - if (start == vma->vm_start) { - start += PAGE_SIZE; - nr_pages--; - } + if (stack_guard_page(vma, start)) { + addr += PAGE_SIZE; + nr_pages--; } while (nr_pages > 0) { -- cgit v1.2.3 From 6bed99917d414371cd5342158b6ed514ee8fee45 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 20 Aug 2010 16:49:40 -0700 Subject: mm: make stack guard page logic use vm_prev pointer commit 0e8e50e20c837eeec8323bba7dcd25fe5479194c upstream. Like the mlock() change previously, this makes the stack guard check code use vma->vm_prev to see what the mapping below the current stack is, rather than have to look it up with find_vma(). Also, accept an abutting stack segment, since that happens naturally if you split the stack with mlock or mprotect. Tested-by: Ian Campbell Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/memory.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 307bf77fc441..53cf85d44449 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2770,11 +2770,18 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo { address &= PAGE_MASK; if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) { - address -= PAGE_SIZE; - if (find_vma(vma->vm_mm, address) != vma) - return -ENOMEM; + struct vm_area_struct *prev = vma->vm_prev; + + /* + * Is there a mapping abutting this one below? + * + * That's only ok if it's the same stack mapping + * that has gotten split.. + */ + if (prev && prev->vm_end == address) + return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM; - expand_stack(vma, address); + expand_stack(vma, address - PAGE_SIZE); } return 0; } -- cgit v1.2.3 From 1f0a86afdf7fc4782c6d3bbd30f21cbce9b5b6f9 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 27 Jul 2010 23:29:52 -0700 Subject: x86, asm: Clean up and simplify set_64bit() commit 69309a05907546fb686b251d4ab041c26afe1e1d upstream. Clean up and simplify set_64bit(). This code is quite old (1.3.11) and contains a fair bit of auxilliary machinery that current versions of gcc handle just fine automatically. Worse, the auxilliary machinery can actually cause an unnecessary spill to memory. Furthermore, the loading of the old value inside the loop in the 32-bit case is unnecessary: if the value doesn't match, the CMPXCHG8B instruction will already have loaded the "new previous" value for us. Clean up the comment, too, and remove page references to obsolete versions of the Intel SDM. Signed-off-by: H. Peter Anvin LKML-Reference: Tested-by: Mark Stanovich Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/cmpxchg_32.h | 67 ++++++++++++--------------------------- arch/x86/include/asm/cmpxchg_64.h | 4 +-- 2 files changed, 21 insertions(+), 50 deletions(-) diff --git a/arch/x86/include/asm/cmpxchg_32.h b/arch/x86/include/asm/cmpxchg_32.h index c1cf59d72f09..20955ea7bc12 100644 --- a/arch/x86/include/asm/cmpxchg_32.h +++ b/arch/x86/include/asm/cmpxchg_32.h @@ -53,60 +53,33 @@ struct __xchg_dummy { __xchg((v), (ptr), sizeof(*ptr)) /* - * The semantics of XCHGCMP8B are a bit strange, this is why - * there is a loop and the loading of %%eax and %%edx has to - * be inside. This inlines well in most cases, the cached - * cost is around ~38 cycles. (in the future we might want - * to do an SIMD/3DNOW!/MMX/FPU 64-bit store here, but that - * might have an implicit FPU-save as a cost, so it's not - * clear which path to go.) + * CMPXCHG8B only writes to the target if we had the previous + * value in registers, otherwise it acts as a read and gives us the + * "new previous" value. That is why there is a loop. Preloading + * EDX:EAX is a performance optimization: in the common case it means + * we need only one locked operation. * - * cmpxchg8b must be used with the lock prefix here to allow - * the instruction to be executed atomically, see page 3-102 - * of the instruction set reference 24319102.pdf. We need - * the reader side to see the coherent 64bit value. + * A SIMD/3DNOW!/MMX/FPU 64-bit store here would require at the very + * least an FPU save and/or %cr0.ts manipulation. + * + * cmpxchg8b must be used with the lock prefix here to allow the + * instruction to be executed atomically. We need to have the reader + * side to see the coherent 64bit value. */ -static inline void __set_64bit(unsigned long long *ptr, - unsigned int low, unsigned int high) +static inline void set_64bit(volatile u64 *ptr, u64 value) { + u32 low = value; + u32 high = value >> 32; + u64 prev = *ptr; + asm volatile("\n1:\t" - "movl (%1), %%eax\n\t" - "movl 4(%1), %%edx\n\t" - LOCK_PREFIX "cmpxchg8b (%1)\n\t" + LOCK_PREFIX "cmpxchg8b %0\n\t" "jnz 1b" - : "=m" (*ptr) - : "D" (ptr), - "b" (low), - "c" (high) - : "ax", "dx", "memory"); -} - -static inline void __set_64bit_constant(unsigned long long *ptr, - unsigned long long value) -{ - __set_64bit(ptr, (unsigned int)value, (unsigned int)(value >> 32)); -} - -#define ll_low(x) *(((unsigned int *)&(x)) + 0) -#define ll_high(x) *(((unsigned int *)&(x)) + 1) - -static inline void __set_64bit_var(unsigned long long *ptr, - unsigned long long value) -{ - __set_64bit(ptr, ll_low(value), ll_high(value)); + : "=m" (*ptr), "+A" (prev) + : "b" (low), "c" (high) + : "memory"); } -#define set_64bit(ptr, value) \ - (__builtin_constant_p((value)) \ - ? __set_64bit_constant((ptr), (value)) \ - : __set_64bit_var((ptr), (value))) - -#define _set_64bit(ptr, value) \ - (__builtin_constant_p(value) \ - ? __set_64bit(ptr, (unsigned int)(value), \ - (unsigned int)((value) >> 32)) \ - : __set_64bit(ptr, ll_low((value)), ll_high((value)))) - extern void __cmpxchg_wrong_size(void); /* diff --git a/arch/x86/include/asm/cmpxchg_64.h b/arch/x86/include/asm/cmpxchg_64.h index b92f147339f3..9596e7c61960 100644 --- a/arch/x86/include/asm/cmpxchg_64.h +++ b/arch/x86/include/asm/cmpxchg_64.h @@ -5,13 +5,11 @@ #define __xg(x) ((volatile long *)(x)) -static inline void set_64bit(volatile unsigned long *ptr, unsigned long val) +static inline void set_64bit(volatile u64 *ptr, u64 val) { *ptr = val; } -#define _set_64bit set_64bit - extern void __xchg_wrong_size(void); extern void __cmpxchg_wrong_size(void); -- cgit v1.2.3 From 5ef5852385892aa4d9331b5bc20962b87c91d562 Mon Sep 17 00:00:00 2001 From: Carsten Otte Date: Fri, 6 Aug 2010 18:19:22 +0200 Subject: slab: fix object alignment commit 1ab335d8f85792e3b107ff8237d53cf64db714df upstream. This patch fixes alignment of slab objects in case CONFIG_DEBUG_PAGEALLOC is active. Before this spot in kmem_cache_create, we have this situation: - align contains the required alignment of the object - cachep->obj_offset is 0 or equals align in case of CONFIG_DEBUG_SLAB - size equals the size of the object, or object plus trailing redzone in case of CONFIG_DEBUG_SLAB This spot tries to fill one page per object if the object is in certain size limits, however setting obj_offset to PAGE_SIZE - size does break the object alignment since size may not be aligned with the required alignment. This patch simply adds an ALIGN(size, align) to the equation and fixes the object size detection accordingly. This code in drivers/s390/cio/qdio_setup_init has lead to incorrectly aligned slab objects (sizeof(struct qdio_q) equals 1792): qdio_q_cache = kmem_cache_create("qdio_q", sizeof(struct qdio_q), 256, 0, NULL); Acked-by: Christoph Lameter Signed-off-by: Carsten Otte Signed-off-by: Pekka Enberg Signed-off-by: Greg Kroah-Hartman --- mm/slab.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index e49f8f46f46d..e4f747fcbdf4 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2331,8 +2331,8 @@ kmem_cache_create (const char *name, size_t size, size_t align, } #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC) if (size >= malloc_sizes[INDEX_L3 + 1].cs_size - && cachep->obj_size > cache_line_size() && size < PAGE_SIZE) { - cachep->obj_offset += PAGE_SIZE - size; + && cachep->obj_size > cache_line_size() && ALIGN(size, align) < PAGE_SIZE) { + cachep->obj_offset += PAGE_SIZE - ALIGN(size, align); size = PAGE_SIZE; } #endif -- cgit v1.2.3 From ef0b95594718adf4de1e8fb8fa4bce18039a5577 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 4 Aug 2010 17:30:21 -0700 Subject: sparc64: Add missing ID to parport probing code. [ Upstream commit bf8253bf5e7cfe17dd53e3f6340a45b11d9fb51c ] SunBlade-2500 has 'parallel' device node with compatible property "pnpALI,1533,3" so add that to the ID table. Reported-by: Mikael Pettersson Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/include/asm/parport.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/sparc/include/asm/parport.h b/arch/sparc/include/asm/parport.h index c333b8d0949b..d21ad5089d20 100644 --- a/arch/sparc/include/asm/parport.h +++ b/arch/sparc/include/asm/parport.h @@ -228,6 +228,10 @@ static const struct of_device_id ecpp_match[] = { .name = "parallel", .compatible = "ns87317-ecpp", }, + { + .name = "parallel", + .compatible = "pnpALI,1533,3", + }, {}, }; -- cgit v1.2.3 From e214c09dc0c3a34b543cbcbacd712c5ba1a1d76c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 17 Aug 2010 17:09:53 -0700 Subject: sparc64: Fix rwsem constant bug leading to hangs. [ Upstream commit ef201bebe5afc91a2b99b45dacc8c6dd88ca9e58 ] As noticed by Linus, it is critical that some of the rwsem constants be signed. Yet, hex constants are unsigned unless explicitly casted or negated. The most critical one is RWSEM_WAITING_BIAS. This bug was exacerbated by commit 424acaaeb3a3932d64a9b4bd59df6cf72c22d8f3 ("rwsem: wake queued readers when writer blocks on active read lock") Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/include/asm/rwsem-const.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc/include/asm/rwsem-const.h b/arch/sparc/include/asm/rwsem-const.h index a303c9d64d84..e4c61a18bb28 100644 --- a/arch/sparc/include/asm/rwsem-const.h +++ b/arch/sparc/include/asm/rwsem-const.h @@ -5,7 +5,7 @@ #define RWSEM_UNLOCKED_VALUE 0x00000000 #define RWSEM_ACTIVE_BIAS 0x00000001 #define RWSEM_ACTIVE_MASK 0x0000ffff -#define RWSEM_WAITING_BIAS 0xffff0000 +#define RWSEM_WAITING_BIAS (-0x00010000) #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) -- cgit v1.2.3 From bbb0cf2f72e98162c7387123dd1f26938c8e1183 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 18 Aug 2010 14:47:23 -0700 Subject: sparc64: Fix atomic64_t routine return values. [ Upstream commits 86fa04b8742ac681d470786f55e2403ada0075b2 and b10f997bb0f4e5b34d447f498fb85834a40d3acb ] Should return 'long' instead of 'int'. Thanks to Dimitris Michailidis and Tony Luck. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/include/asm/atomic_64.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h index 2050ca02c423..bdb2ff880bdd 100644 --- a/arch/sparc/include/asm/atomic_64.h +++ b/arch/sparc/include/asm/atomic_64.h @@ -20,14 +20,14 @@ #define atomic64_set(v, i) (((v)->counter) = i) extern void atomic_add(int, atomic_t *); -extern void atomic64_add(int, atomic64_t *); +extern void atomic64_add(long, atomic64_t *); extern void atomic_sub(int, atomic_t *); -extern void atomic64_sub(int, atomic64_t *); +extern void atomic64_sub(long, atomic64_t *); extern int atomic_add_ret(int, atomic_t *); -extern int atomic64_add_ret(int, atomic64_t *); +extern long atomic64_add_ret(long, atomic64_t *); extern int atomic_sub_ret(int, atomic_t *); -extern int atomic64_sub_ret(int, atomic64_t *); +extern long atomic64_sub_ret(long, atomic64_t *); #define atomic_dec_return(v) atomic_sub_ret(1, v) #define atomic64_dec_return(v) atomic64_sub_ret(1, v) @@ -91,7 +91,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n))) #define atomic64_xchg(v, new) (xchg(&((v)->counter), new)) -static inline int atomic64_add_unless(atomic64_t *v, long a, long u) +static inline long atomic64_add_unless(atomic64_t *v, long a, long u) { long c, old; c = atomic64_read(v); -- cgit v1.2.3 From 922ab18b2778c82bc52acd43ab0e41b31847afc3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 15 Aug 2010 00:26:14 -0700 Subject: sparc: Really fix "console=" for serial consoles. [ Upstream commit 0a492896ac07336c98f37ad7fab4a6387b6ada78 ] If a video head and keyboard are hooked up, specifying "console=ttyS0" or similar to use a serial console will not work properly. The key issue is that we must register all serial console capable devices with register_console(), otherwise the command line specified device won't be found. The sun serial drivers would only register themselves as console devices if the OpenFirmware specified console device node matched. To fix this part we now unconditionally get the serial console register by setting serial_drv->cons always. Secondarily we must not add_preferred_console() using the firmware provided console setting if the user gaven an override on the kernel command line using "console=" The "primary framebuffer" matching logic was always triggering o n openfirmware device node match, make it not when a command line override was given. Reported-by: Frans Pop Tested-by: Frans Pop Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/include/asm/fb.h | 4 ++++ drivers/serial/suncore.c | 15 +++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/arch/sparc/include/asm/fb.h b/arch/sparc/include/asm/fb.h index e834880be204..2173432ad7f7 100644 --- a/arch/sparc/include/asm/fb.h +++ b/arch/sparc/include/asm/fb.h @@ -1,5 +1,6 @@ #ifndef _SPARC_FB_H_ #define _SPARC_FB_H_ +#include #include #include #include @@ -18,6 +19,9 @@ static inline int fb_is_primary_device(struct fb_info *info) struct device *dev = info->device; struct device_node *node; + if (console_set_on_cmdline) + return 0; + node = dev->of_node; if (node && node == of_console_device) diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c index 544f2e25d0e5..6381a0282ee7 100644 --- a/drivers/serial/suncore.c +++ b/drivers/serial/suncore.c @@ -55,7 +55,12 @@ EXPORT_SYMBOL(sunserial_unregister_minors); int sunserial_console_match(struct console *con, struct device_node *dp, struct uart_driver *drv, int line, bool ignore_line) { - if (!con || of_console_device != dp) + if (!con) + return 0; + + drv->cons = con; + + if (of_console_device != dp) return 0; if (!ignore_line) { @@ -69,12 +74,10 @@ int sunserial_console_match(struct console *con, struct device_node *dp, return 0; } - con->index = line; - drv->cons = con; - - if (!console_set_on_cmdline) + if (!console_set_on_cmdline) { + con->index = line; add_preferred_console(con->name, line, NULL); - + } return 1; } EXPORT_SYMBOL(sunserial_console_match); -- cgit v1.2.3 From f49fd7f79a1e35fd2a322f1af4d7a9ce075d972b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 18 Aug 2010 22:56:36 -0700 Subject: bridge: add rcu_read_lock on transmit [ Upstream commit eeaf61d8891f9c9ed12c1a667e72bf83f0857954 ] Long ago, when bridge was converted to RCU, rcu lock was equivalent to having preempt disabled. RCU has changed a lot since then and bridge code was still assuming the since transmit was called with bottom half disabled, it was RCU safe. Signed-off-by: Stephen Hemminger Tested-by: Johannes Berg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/bridge/br_device.c | 4 +++- net/bridge/br_fdb.c | 2 +- net/bridge/br_input.c | 6 +++--- net/bridge/br_stp_bpdu.c | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 753fc4221f3c..4cec8051164d 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -22,7 +22,7 @@ #include #include "br_private.h" -/* net device transmit always called with no BH (preempt_disabled) */ +/* net device transmit always called with BH disabled */ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_bridge *br = netdev_priv(dev); @@ -46,6 +46,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) skb_reset_mac_header(skb); skb_pull(skb, ETH_HLEN); + rcu_read_lock(); if (is_multicast_ether_addr(dest)) { if (br_multicast_rcv(br, NULL, skb)) goto out; @@ -61,6 +62,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) br_flood_deliver(br, skb); out: + rcu_read_unlock(); return NETDEV_TX_OK; } diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index b01dde35a69e..7204ad3aff65 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -214,7 +214,7 @@ void br_fdb_delete_by_port(struct net_bridge *br, spin_unlock_bh(&br->hash_lock); } -/* No locking or refcounting, assumes caller has no preempt (rcu_read_lock) */ +/* No locking or refcounting, assumes caller has rcu_read_lock */ struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, const unsigned char *addr) { diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index d36e700f7a26..114365c9eb1c 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -37,7 +37,7 @@ static int br_pass_frame_up(struct sk_buff *skb) netif_receive_skb); } -/* note: already called with rcu_read_lock (preempt_disabled) */ +/* note: already called with rcu_read_lock */ int br_handle_frame_finish(struct sk_buff *skb) { const unsigned char *dest = eth_hdr(skb)->h_dest; @@ -108,7 +108,7 @@ drop: goto out; } -/* note: already called with rcu_read_lock (preempt_disabled) */ +/* note: already called with rcu_read_lock */ static int br_handle_local_finish(struct sk_buff *skb) { struct net_bridge_port *p = rcu_dereference(skb->dev->br_port); @@ -133,7 +133,7 @@ static inline int is_link_local(const unsigned char *dest) /* * Called via br_handle_frame_hook. * Return NULL if skb is handled - * note: already called with rcu_read_lock (preempt_disabled) + * note: already called with rcu_read_lock */ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb) { diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index 217bd225a42f..5854e8285a9c 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c @@ -131,7 +131,7 @@ void br_send_tcn_bpdu(struct net_bridge_port *p) /* * Called from llc. * - * NO locks, but rcu_read_lock (preempt_disabled) + * NO locks, but rcu_read_lock */ void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb, struct net_device *dev) -- cgit v1.2.3 From 8eb6fff671bbe0ec4ae43f5356fe9029b3dfe984 Mon Sep 17 00:00:00 2001 From: Dmitry Popov Date: Thu, 29 Jul 2010 01:59:36 +0000 Subject: tcp: cookie transactions setsockopt memory leak [ Upstream commit a3bdb549e30e7a263f7a589747c40e9c50110315 ] There is a bug in do_tcp_setsockopt(net/ipv4/tcp.c), TCP_COOKIE_TRANSACTIONS case. In some cases (when tp->cookie_values == NULL) new tcp_cookie_values structure can be allocated (at cvp), but not bound to tp->cookie_values. So a memory leak occurs. Signed-off-by: Dmitry Popov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 65afeaec15b7..c259714c5596 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2176,6 +2176,8 @@ static int do_tcp_setsockopt(struct sock *sk, int level, GFP_KERNEL); if (cvp == NULL) return -ENOMEM; + + kref_init(&cvp->kref); } lock_sock(sk); tp->rx_opt.cookie_in_always = @@ -2190,12 +2192,11 @@ static int do_tcp_setsockopt(struct sock *sk, int level, */ kref_put(&tp->cookie_values->kref, tcp_cookie_values_release); - kref_init(&cvp->kref); - tp->cookie_values = cvp; } else { cvp = tp->cookie_values; } } + if (cvp != NULL) { cvp->cookie_desired = ctd.tcpct_cookie_desired; @@ -2209,6 +2210,8 @@ static int do_tcp_setsockopt(struct sock *sk, int level, cvp->s_data_desired = ctd.tcpct_s_data_desired; cvp->s_data_constant = 0; /* false */ } + + tp->cookie_values = cvp; } release_sock(sk); return err; -- cgit v1.2.3 From 1fa22dac6cea18fa4b4806427c7a895400f5b041 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 29 Jul 2010 01:12:31 +0000 Subject: bridge: Fix skb leak when multicast parsing fails on TX [ Upstream commit 6d1d1d398cb7db7a12c5d652d50f85355345234f ] On the bridge TX path we're leaking an skb when br_multicast_rcv returns an error. Reported-by: David Lamparter Signed-off-by: Herbert Xu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/bridge/br_device.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 4cec8051164d..f49bcd9d9113 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -48,8 +48,10 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) rcu_read_lock(); if (is_multicast_ether_addr(dest)) { - if (br_multicast_rcv(br, NULL, skb)) + if (br_multicast_rcv(br, NULL, skb)) { + kfree_skb(skb); goto out; + } mdst = br_mdb_get(br, skb); if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) -- cgit v1.2.3 From 51a9e83a53f2b20be0611349180d5b125471a86a Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Thu, 29 Jul 2010 14:04:18 +0000 Subject: act_nat: the checksum of ICMP doesn't have pseudo header [ Upstream commit 3a3dfb062c2e086c202d34f09ce29634515ad256 ] after updating the value of the ICMP payload, inet_proto_csum_replace4() should be called with zero pseudohdr. Signed-off-by: Changli Gao Acked-by: Herbert Xu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/act_nat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c index 724553e8ed7b..4e7c24ae2ac5 100644 --- a/net/sched/act_nat.c +++ b/net/sched/act_nat.c @@ -246,7 +246,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, iph->saddr = new_addr; inet_proto_csum_replace4(&icmph->checksum, skb, addr, new_addr, - 1); + 0); break; } default: -- cgit v1.2.3 From 1a1b1d29b0d472da80f23fc58885dc2151b62b72 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Wed, 11 Aug 2010 16:12:35 -0700 Subject: can: add limit for nframes and clean up signed/unsigned variables [ Upstream commit 5b75c4973ce779520b9d1e392483207d6f842cde ] This patch adds a limit for nframes as the number of frames in TX_SETUP and RX_SETUP are derived from a single byte multiplex value by default. Use-cases that would require to send/filter more than 256 CAN frames should be implemented in userspace for complexity reasons anyway. Additionally the assignments of unsigned values from userspace to signed values in kernelspace and vice versa are fixed by using unsigned values in kernelspace consistently. Signed-off-by: Oliver Hartkopp Reported-by: Ben Hawkes Acked-by: Urs Thuermann Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/can/bcm.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/net/can/bcm.c b/net/can/bcm.c index 9c65e9deb9c3..08ffe9e4be20 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -60,6 +60,13 @@ #include #include +/* + * To send multiple CAN frame content within TX_SETUP or to filter + * CAN messages with multiplex index within RX_SETUP, the number of + * different filters is limited to 256 due to the one byte index value. + */ +#define MAX_NFRAMES 256 + /* use of last_frames[index].can_dlc */ #define RX_RECV 0x40 /* received data for this element */ #define RX_THR 0x80 /* element not been sent due to throttle feature */ @@ -89,16 +96,16 @@ struct bcm_op { struct list_head list; int ifindex; canid_t can_id; - int flags; + u32 flags; unsigned long frames_abs, frames_filtered; struct timeval ival1, ival2; struct hrtimer timer, thrtimer; struct tasklet_struct tsklet, thrtsklet; ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg; int rx_ifindex; - int count; - int nframes; - int currframe; + u32 count; + u32 nframes; + u32 currframe; struct can_frame *frames; struct can_frame *last_frames; struct can_frame sframe; @@ -175,7 +182,7 @@ static int bcm_proc_show(struct seq_file *m, void *v) seq_printf(m, "rx_op: %03X %-5s ", op->can_id, bcm_proc_getifname(ifname, op->ifindex)); - seq_printf(m, "[%d]%c ", op->nframes, + seq_printf(m, "[%u]%c ", op->nframes, (op->flags & RX_CHECK_DLC)?'d':' '); if (op->kt_ival1.tv64) seq_printf(m, "timeo=%lld ", @@ -198,7 +205,7 @@ static int bcm_proc_show(struct seq_file *m, void *v) list_for_each_entry(op, &bo->tx_ops, list) { - seq_printf(m, "tx_op: %03X %s [%d] ", + seq_printf(m, "tx_op: %03X %s [%u] ", op->can_id, bcm_proc_getifname(ifname, op->ifindex), op->nframes); @@ -283,7 +290,7 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head, struct can_frame *firstframe; struct sockaddr_can *addr; struct sock *sk = op->sk; - int datalen = head->nframes * CFSIZ; + unsigned int datalen = head->nframes * CFSIZ; int err; skb = alloc_skb(sizeof(*head) + datalen, gfp_any()); @@ -468,7 +475,7 @@ rx_changed_settime: * bcm_rx_cmp_to_index - (bit)compares the currently received data to formerly * received data stored in op->last_frames[] */ -static void bcm_rx_cmp_to_index(struct bcm_op *op, int index, +static void bcm_rx_cmp_to_index(struct bcm_op *op, unsigned int index, const struct can_frame *rxdata) { /* @@ -554,7 +561,8 @@ static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer) /* * bcm_rx_do_flush - helper for bcm_rx_thr_flush */ -static inline int bcm_rx_do_flush(struct bcm_op *op, int update, int index) +static inline int bcm_rx_do_flush(struct bcm_op *op, int update, + unsigned int index) { if ((op->last_frames) && (op->last_frames[index].can_dlc & RX_THR)) { if (update) @@ -575,7 +583,7 @@ static int bcm_rx_thr_flush(struct bcm_op *op, int update) int updated = 0; if (op->nframes > 1) { - int i; + unsigned int i; /* for MUX filter we start at index 1 */ for (i = 1; i < op->nframes; i++) @@ -624,7 +632,7 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data) { struct bcm_op *op = (struct bcm_op *)data; const struct can_frame *rxframe = (struct can_frame *)skb->data; - int i; + unsigned int i; /* disable timeout */ hrtimer_cancel(&op->timer); @@ -822,14 +830,15 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, { struct bcm_sock *bo = bcm_sk(sk); struct bcm_op *op; - int i, err; + unsigned int i; + int err; /* we need a real device to send frames */ if (!ifindex) return -ENODEV; - /* we need at least one can_frame */ - if (msg_head->nframes < 1) + /* check nframes boundaries - we need at least one can_frame */ + if (msg_head->nframes < 1 || msg_head->nframes > MAX_NFRAMES) return -EINVAL; /* check the given can_id */ @@ -993,6 +1002,10 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, msg_head->nframes = 0; } + /* the first element contains the mux-mask => MAX_NFRAMES + 1 */ + if (msg_head->nframes > MAX_NFRAMES + 1) + return -EINVAL; + if ((msg_head->flags & RX_RTR_FRAME) && ((msg_head->nframes != 1) || (!(msg_head->can_id & CAN_RTR_FLAG)))) -- cgit v1.2.3 From b46ddc15f90dca13564f9c2be6210d7d9fef014b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 4 Aug 2010 23:38:06 +0000 Subject: isdn: fix information leak [ Upstream commit 4b030d4288a569d6bdeca884d7f102d951f097f2 ] The main motivation of this patch changing strcpy() to strlcpy(). We strcpy() to copy a 48 byte buffers into a 49 byte buffers. So at best the last byte has leaked information, or maybe there is an overflow? Anyway, this patch closes the information leaks by zeroing the memory and the calls to strlcpy() prevent overflows. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/sc/ioctl.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c index 1081091bbfaf..2655e3aab895 100644 --- a/drivers/isdn/sc/ioctl.c +++ b/drivers/isdn/sc/ioctl.c @@ -174,7 +174,7 @@ int sc_ioctl(int card, scs_ioctl *data) pr_debug("%s: SCIOGETSPID: ioctl received\n", sc_adapter[card]->devicename); - spid = kmalloc(SCIOC_SPIDSIZE, GFP_KERNEL); + spid = kzalloc(SCIOC_SPIDSIZE, GFP_KERNEL); if (!spid) { kfree(rcvmsg); return -ENOMEM; @@ -194,7 +194,7 @@ int sc_ioctl(int card, scs_ioctl *data) kfree(rcvmsg); return status; } - strcpy(spid, rcvmsg->msg_data.byte_array); + strlcpy(spid, rcvmsg->msg_data.byte_array, SCIOC_SPIDSIZE); /* * Package the switch type and send to user space @@ -272,12 +272,12 @@ int sc_ioctl(int card, scs_ioctl *data) return status; } - dn = kmalloc(SCIOC_DNSIZE, GFP_KERNEL); + dn = kzalloc(SCIOC_DNSIZE, GFP_KERNEL); if (!dn) { kfree(rcvmsg); return -ENOMEM; } - strcpy(dn, rcvmsg->msg_data.byte_array); + strlcpy(dn, rcvmsg->msg_data.byte_array, SCIOC_DNSIZE); kfree(rcvmsg); /* @@ -348,7 +348,7 @@ int sc_ioctl(int card, scs_ioctl *data) pr_debug("%s: SCIOSTAT: ioctl received\n", sc_adapter[card]->devicename); - bi = kmalloc (sizeof(boardInfo), GFP_KERNEL); + bi = kzalloc(sizeof(boardInfo), GFP_KERNEL); if (!bi) { kfree(rcvmsg); return -ENOMEM; -- cgit v1.2.3 From 525127bf8070a869857a66c1c5c6c5324bb335dc Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Thu, 5 Aug 2010 01:19:11 +0000 Subject: net: Fix napi_gro_frags vs netpoll path [ Upstream commit ce9e76c8450fc248d3e1fc16ef05e6eb50c02fa5 ] The netpoll_rx_on() check in __napi_gro_receive() skips part of the "common" GRO_NORMAL path, especially "pull:" in dev_gro_receive(), where at least eth header should be copied for entirely paged skbs. Signed-off-by: Jarek Poplawski Acked-by: Herbert Xu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 1f466e82ac33..bcfb093732a5 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3064,7 +3064,7 @@ enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) int mac_len; enum gro_result ret; - if (!(skb->dev->features & NETIF_F_GRO)) + if (!(skb->dev->features & NETIF_F_GRO) || netpoll_rx_on(skb)) goto normal; if (skb_is_gso(skb) || skb_has_frags(skb)) @@ -3151,9 +3151,6 @@ __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) { struct sk_buff *p; - if (netpoll_rx_on(skb)) - return GRO_NORMAL; - for (p = napi->gro_list; p; p = p->next) { NAPI_GRO_CB(p)->same_flow = (p->dev == skb->dev) && -- cgit v1.2.3 From 4c0ef2f2c0ef4245486124b84ba0ec9a2b4b3899 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Wed, 11 Aug 2010 02:02:10 +0000 Subject: net: Fix a memmove bug in dev_gro_receive() [ Upstream commit e5093aec2e6b60c3df2420057ffab9ed4a6d2792 ] >Xin Xiaohui wrote: > I looked into the code dev_gro_receive(), found the code here: > if the frags[0] is pulled to 0, then the page will be released, > and memmove() frags left. > Is that right? I'm not sure if memmove do right or not, but > frags[0].size is never set after memove at least. what I think > a simple way is not to do anything if we found frags[0].size == 0. > The patch is as followed. ... This version of the patch fixes the bug directly in memmove. Reported-by: "Xin, Xiaohui" Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index bcfb093732a5..c4e89ef60160 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3133,7 +3133,7 @@ pull: put_page(skb_shinfo(skb)->frags[0].page); memmove(skb_shinfo(skb)->frags, skb_shinfo(skb)->frags + 1, - --skb_shinfo(skb)->nr_frags); + --skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t)); } } -- cgit v1.2.3 From 0ff3da3bc0827cbc60d9ef37ac26d72814125fa6 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Fri, 6 Aug 2010 00:22:35 +0000 Subject: pkt_sched: Fix sch_sfq vs tcf_bind_filter oops [ Upstream commit eb4a5527b1f0d581ac217c80ef3278ed5e38693c ] Since there was added ->tcf_chain() method without ->bind_tcf() to sch_sfq class options, there is oops when a filter is added with the classid parameter. Fixes commit 7d2681a6ff4f9ab5e48d02550b4c6338f1638998 netdev thread: null pointer at cls_api.c Signed-off-by: Jarek Poplawski Reported-by: Franchoze Eric Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/sch_sfq.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index c65762823f5e..9ba71ba0f8f0 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -502,6 +502,12 @@ static unsigned long sfq_get(struct Qdisc *sch, u32 classid) return 0; } +static unsigned long sfq_bind(struct Qdisc *sch, unsigned long parent, + u32 classid) +{ + return 0; +} + static struct tcf_proto **sfq_find_tcf(struct Qdisc *sch, unsigned long cl) { struct sfq_sched_data *q = qdisc_priv(sch); @@ -556,6 +562,7 @@ static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg) static const struct Qdisc_class_ops sfq_class_ops = { .get = sfq_get, .tcf_chain = sfq_find_tcf, + .bind_tcf = sfq_bind, .dump = sfq_dump_class, .dump_stats = sfq_dump_class_stats, .walk = sfq_walk, -- cgit v1.2.3 From 34793c34a78af4043f119c7fc332526d5b012fd0 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Tue, 10 Aug 2010 22:31:02 +0000 Subject: pkt_sched: Fix sch_sfq vs tc_modify_qdisc oops [ Upstream commit 41065fba846e795b31b17e4dec01cb904d56c6cd ] sch_sfq as a classful qdisc needs the .leaf handler. Otherwise, there is an oops possible in tc_modify_qdisc()/check_loop(). Fixes commit 7d2681a6ff4f9ab5e48d02550b4c6338f1638998 Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/sch_sfq.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 9ba71ba0f8f0..a9be0ef65e87 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -497,6 +497,11 @@ nla_put_failure: return -1; } +static struct Qdisc *sfq_leaf(struct Qdisc *sch, unsigned long arg) +{ + return NULL; +} + static unsigned long sfq_get(struct Qdisc *sch, u32 classid) { return 0; @@ -560,6 +565,7 @@ static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg) } static const struct Qdisc_class_ops sfq_class_ops = { + .leaf = sfq_leaf, .get = sfq_get, .tcf_chain = sfq_find_tcf, .bind_tcf = sfq_bind, -- cgit v1.2.3 From 1378008ccdfdfcedbd6503f00e52124bfce1e0f7 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Sat, 7 Aug 2010 20:35:43 -0700 Subject: net: disable preemption before call smp_processor_id() [ Upstream commit cece1945bffcf1a823cdfa36669beae118419351 ] Although netif_rx() isn't expected to be called in process context with preemption enabled, it'd better handle this case. And this is why get_cpu() is used in the non-RPS #ifdef branch. If tree RCU is selected, rcu_read_lock() won't disable preemption, so preempt_disable() should be called explictly. Signed-off-by: Changli Gao Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index c4e89ef60160..95cc48618043 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2504,6 +2504,7 @@ int netif_rx(struct sk_buff *skb) struct rps_dev_flow voidflow, *rflow = &voidflow; int cpu; + preempt_disable(); rcu_read_lock(); cpu = get_rps_cpu(skb->dev, skb, &rflow); @@ -2513,6 +2514,7 @@ int netif_rx(struct sk_buff *skb) ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail); rcu_read_unlock(); + preempt_enable(); } #else { -- cgit v1.2.3 From 1cd65f87cbf31684d778155b31ea32384f8df5d1 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Thu, 29 Jul 2010 13:41:46 +0000 Subject: act_nat: fix wild pointer [ Upstream commit 072d79a31a3b870b49886f4347e23f81b7eca3ac ] pskb_may_pull() may change skb pointers, so adjust icmph after pskb_may_pull(). Signed-off-by: Changli Gao Acked-by: Herbert Xu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/act_nat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c index 4e7c24ae2ac5..abbf4fa66a0b 100644 --- a/net/sched/act_nat.c +++ b/net/sched/act_nat.c @@ -218,6 +218,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + sizeof(*iph))) goto drop; + icmph = (void *)(skb_network_header(skb) + ihl); iph = (void *)(icmph + 1); if (egress) addr = iph->daddr; -- cgit v1.2.3 From ea554ee37bcf4ad4f70b100287ffc84c2cf33066 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 6 Aug 2010 16:34:43 +0100 Subject: Fix init ordering of /dev/console vs callers of modprobe commit 31d1d48e199e99077fb30f6fb9a793be7bec756f upstream. Make /dev/console get initialised before any initialisation routine that invokes modprobe because if modprobe fails, it's going to want to open /dev/console, presumably to write an error message to. The problem with that is that if the /dev/console driver is not yet initialised, the chardev handler will call request_module() to invoke modprobe, which will fail, because we never compile /dev/console as a module. This will lead to a modprobe loop, showing the following in the kernel log: request_module: runaway loop modprobe char-major-5-1 request_module: runaway loop modprobe char-major-5-1 request_module: runaway loop modprobe char-major-5-1 request_module: runaway loop modprobe char-major-5-1 request_module: runaway loop modprobe char-major-5-1 This can happen, for example, when the built in md5 module can't find the built in cryptomgr module (because the latter fails to initialise). The md5 module comes before the call to tty_init(), presumably because 'crypto' comes before 'drivers' alphabetically. Fix this by calling tty_init() from chrdev_init(). Signed-off-by: David Howells Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/char/mem.c | 2 +- drivers/char/tty_io.c | 4 ++-- fs/char_dev.c | 1 + include/linux/tty.h | 3 +++ 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/char/mem.c b/drivers/char/mem.c index f54dab8acdcd..a398ecdbd758 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -916,7 +916,7 @@ static int __init chr_dev_init(void) NULL, devlist[minor].name); } - return 0; + return tty_init(); } fs_initcall(chr_dev_init); diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index d71f0fc34b46..507441ac6edb 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -3128,7 +3128,7 @@ static struct cdev tty_cdev, console_cdev; * Ok, now we can initialize the rest of the tty devices and can count * on memory allocations, interrupts etc.. */ -static int __init tty_init(void) +int __init tty_init(void) { cdev_init(&tty_cdev, &tty_fops); if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || @@ -3149,4 +3149,4 @@ static int __init tty_init(void) #endif return 0; } -module_init(tty_init); + diff --git a/fs/char_dev.c b/fs/char_dev.c index d6db933df2b2..f80a4f25123c 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "internal.h" diff --git a/include/linux/tty.h b/include/linux/tty.h index 931078b73226..7802a243ee13 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -552,6 +552,9 @@ static inline void tty_audit_push_task(struct task_struct *tsk, } #endif +/* tty_io.c */ +extern int __init tty_init(void); + /* tty_ioctl.c */ extern int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); -- cgit v1.2.3 From 1cfe75af2d0dd55aa30acbff82e37598d07c2763 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 12 Aug 2010 03:53:55 +0100 Subject: gen_nand: Test if nr_chips field is valid commit 01cd2ababddd55a127caa1cd20d570637e0d42e1 upstream. Signed-off-by: Marek Vasut Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/plat_nand.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index 90e143e5ad3e..317aff428e42 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c @@ -37,6 +37,11 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) struct resource *res; int err = 0; + if (pdata->chip.nr_chips < 1) { + dev_err(&pdev->dev, "invalid number of chips specified\n"); + return -EINVAL; + } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENXIO; -- cgit v1.2.3 From 9a2faa7b3b4876d76345f4eb82032c3bbd8da259 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Mon, 5 Jul 2010 14:19:14 +0000 Subject: isdn/gigaset: reduce syslog spam commit 7d060ed2877ff6d00e7238226edbaf91493d6d0b upstream. Downgrade some error messages which occur frequently during normal operation to debug messages. Impact: logging Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/gigaset/capi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 6fbe8999c419..9e168270b3a1 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -378,13 +378,13 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb) ++bcs->trans_up; if (!ap) { - dev_err(cs->dev, "%s: no application\n", __func__); + gig_dbg(DEBUG_MCMD, "%s: application gone", __func__); return; } /* don't send further B3 messages if disconnected */ if (bcs->apconnstate < APCONN_ACTIVE) { - gig_dbg(DEBUG_LLDATA, "disconnected, discarding ack"); + gig_dbg(DEBUG_MCMD, "%s: disconnected", __func__); return; } @@ -422,13 +422,14 @@ void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) bcs->trans_down++; if (!ap) { - dev_err(cs->dev, "%s: no application\n", __func__); + gig_dbg(DEBUG_MCMD, "%s: application gone", __func__); + dev_kfree_skb_any(skb); return; } /* don't send further B3 messages if disconnected */ if (bcs->apconnstate < APCONN_ACTIVE) { - gig_dbg(DEBUG_LLDATA, "disconnected, discarding data"); + gig_dbg(DEBUG_MCMD, "%s: disconnected", __func__); dev_kfree_skb_any(skb); return; } @@ -747,7 +748,7 @@ void gigaset_isdn_connD(struct bc_state *bcs) ap = bcs->ap; if (!ap) { spin_unlock_irqrestore(&bcs->aplock, flags); - dev_err(cs->dev, "%s: no application\n", __func__); + gig_dbg(DEBUG_CMD, "%s: application gone", __func__); return; } if (bcs->apconnstate == APCONN_NONE) { @@ -843,7 +844,7 @@ void gigaset_isdn_connB(struct bc_state *bcs) ap = bcs->ap; if (!ap) { spin_unlock_irqrestore(&bcs->aplock, flags); - dev_err(cs->dev, "%s: no application\n", __func__); + gig_dbg(DEBUG_CMD, "%s: application gone", __func__); return; } if (!bcs->apconnstate) { @@ -901,13 +902,12 @@ void gigaset_isdn_connB(struct bc_state *bcs) */ void gigaset_isdn_hupB(struct bc_state *bcs) { - struct cardstate *cs = bcs->cs; struct gigaset_capi_appl *ap = bcs->ap; /* ToDo: assure order of DISCONNECT_B3_IND and DISCONNECT_IND ? */ if (!ap) { - dev_err(cs->dev, "%s: no application\n", __func__); + gig_dbg(DEBUG_CMD, "%s: application gone", __func__); return; } -- cgit v1.2.3 From 83b79480fa5471bf4627470eb85de21d6dcb3537 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 5 Aug 2010 22:23:23 +0000 Subject: isdn: gigaset: add missing unlock commit 7e27a0aeb98d53539bdc38384eee899d6db62617 upstream. We should unlock here. This is the only place where we return from the function with the lock held. The caller isn't expecting it. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller Signed-off-by: Tilman Schmidt Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/gigaset/capi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 9e168270b3a1..05b15edfbfa2 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -1044,6 +1044,7 @@ static inline void remove_appl_from_channel(struct bc_state *bcs, do { if (bcap->bcnext == ap) { bcap->bcnext = bcap->bcnext->bcnext; + spin_unlock_irqrestore(&bcs->aplock, flags); return; } bcap = bcap->bcnext; -- cgit v1.2.3 From fb862f23acf80ceddb345e6bb460eb5fe56eeace Mon Sep 17 00:00:00 2001 From: John Villalovos Date: Fri, 7 May 2010 12:41:40 -0400 Subject: Oprofile: Change CPUIDS from decimal to hex, and add some comments commit 45c34e05c4e3d36e7c44e790241ea11a1d90d54e upstream. Back when the patch was submitted for "Add Xeon 7500 series support to oprofile", Robert Richter had asked for a followon patch that converted all the CPU ID values to hex. I have done that here for the "i386/core_i7" and "i386/atom" class processors in the ppro_init() function and also added some comments on where to find documentation on the Intel processors. Signed-off-by: John L. Villalovos Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman --- arch/x86/oprofile/nmi_int.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index b28d2f1253bb..1ba67dc8006a 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -634,6 +634,18 @@ static int __init ppro_init(char **cpu_type) if (force_arch_perfmon && cpu_has_arch_perfmon) return 0; + /* + * Documentation on identifying Intel processors by CPU family + * and model can be found in the Intel Software Developer's + * Manuals (SDM): + * + * http://www.intel.com/products/processor/manuals/ + * + * As of May 2010 the documentation for this was in the: + * "Intel 64 and IA-32 Architectures Software Developer's + * Manual Volume 3B: System Programming Guide", "Table B-1 + * CPUID Signature Values of DisplayFamily_DisplayModel". + */ switch (cpu_model) { case 0 ... 2: *cpu_type = "i386/ppro"; @@ -655,12 +667,12 @@ static int __init ppro_init(char **cpu_type) case 15: case 23: *cpu_type = "i386/core_2"; break; + case 0x1a: case 0x2e: - case 26: spec = &op_arch_perfmon_spec; *cpu_type = "i386/core_i7"; break; - case 28: + case 0x1c: *cpu_type = "i386/atom"; break; default: -- cgit v1.2.3 From e29eaa0cccca2718836a26dba04ba68e98e42a62 Mon Sep 17 00:00:00 2001 From: Josh Hunt Date: Wed, 4 Aug 2010 20:27:05 -0400 Subject: oprofile: add support for Intel processor model 30 commit a7c55cbee0c1bae9bf5a15a08300e91d88706e45 upstream. Newer Intel processors identifying themselves as model 30 are not recognized by oprofile. model : 30 model name : Intel(R) Xeon(R) CPU X3470 @ 2.93GHz Running oprofile on these machines gives the following: + opcontrol --init + opcontrol --list-events oprofile: available events for CPU type "Intel Architectural Perfmon" See Intel 64 and IA-32 Architectures Software Developer's Manual Volume 3B (Document 253669) Chapter 18 for architectural perfmon events This is a limited set of fallback events because oprofile doesn't know your CPU CPU_CLK_UNHALTED: (counter: all) Clock cycles when not halted (min count: 6000) INST_RETIRED: (counter: all) number of instructions retired (min count: 6000) LLC_MISSES: (counter: all) Last level cache demand requests from this core that missed the LLC (min count: 6000) Unit masks (default 0x41) ---------- 0x41: No unit mask LLC_REFS: (counter: all) Last level cache demand requests from this core (min count: 6000) Unit masks (default 0x4f) ---------- 0x4f: No unit mask BR_MISS_PRED_RETIRED: (counter: all) number of mispredicted branches retired (precise) (min count: 500) + opcontrol --shutdown Tested using oprofile 0.9.6. Signed-off-by: Josh Hunt Reviewed-by: Andi Kleen Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman --- arch/x86/oprofile/nmi_int.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 1ba67dc8006a..f6b48f6c5951 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -668,6 +668,7 @@ static int __init ppro_init(char **cpu_type) *cpu_type = "i386/core_2"; break; case 0x1a: + case 0x1e: case 0x2e: spec = &op_arch_perfmon_spec; *cpu_type = "i386/core_i7"; -- cgit v1.2.3 From 516125a1d2ea63a87969c2b176c5350d49397ec0 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 8 Jul 2010 09:22:46 -0700 Subject: drm/agp/i915: trim stolen space to 32M commit d1d6ca73ef548748e141747e7260798327d6a2c1 upstream. Some BIOSes will claim a large chunk of stolen space. Unless we reclaim it, our aperture for remapping buffer objects will be constrained. So clamp the stolen space to 32M and ignore the rest. Fixes https://bugzilla.kernel.org/show_bug.cgi?id=15469 among others. Adding the ignored stolen memory back into the general pool using the memory hotplug code is left as an exercise for the reader. Signed-off-by: Jesse Barnes Reviewed-by: Simon Farnsworth Tested-by: Artem S. Tashkinov Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/char/agp/intel-gtt.c | 11 ++++++++++- drivers/gpu/drm/i915/i915_dma.c | 8 ++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index a7547150a705..d84af6c9370e 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -25,6 +25,10 @@ #define USE_PCI_DMA_API 1 #endif +/* Max amount of stolen space, anything above will be returned to Linux */ +int intel_max_stolen = 32 * 1024 * 1024; +EXPORT_SYMBOL(intel_max_stolen); + static const struct aper_size_info_fixed intel_i810_sizes[] = { {64, 16384, 4}, @@ -710,7 +714,12 @@ static void intel_i830_init_gtt_entries(void) break; } } - if (gtt_entries > 0) { + if (!local && gtt_entries > intel_max_stolen) { + dev_info(&agp_bridge->dev->dev, + "detected %dK stolen memory, trimming to %dK\n", + gtt_entries / KB(1), intel_max_stolen / KB(1)); + gtt_entries = intel_max_stolen / KB(4); + } else if (gtt_entries > 0) { dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n", gtt_entries / KB(1), local ? "local" : "stolen"); gtt_entries /= KB(4); diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 2305a1234f1e..013a0aeff709 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -40,6 +40,8 @@ #include #include +extern int intel_max_stolen; /* from AGP driver */ + /** * Sets up the hardware status page for devices that need a physical address * in the register. @@ -2104,6 +2106,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (ret) goto out_iomapfree; + if (prealloc_size > intel_max_stolen) { + DRM_INFO("detected %dM stolen memory, trimming to %dM\n", + prealloc_size >> 20, intel_max_stolen >> 20); + prealloc_size = intel_max_stolen; + } + dev_priv->wq = create_singlethread_workqueue("i915"); if (dev_priv->wq == NULL) { DRM_ERROR("Failed to create our workqueue.\n"); -- cgit v1.2.3 From 0d3a7582aa527a5d0107039d24571faa57114bff Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Mon, 9 Aug 2010 14:20:09 -0700 Subject: timekeeping: Fix overflow in rawtime tv_nsec on 32 bit archs commit deda2e81961e96be4f2c09328baca4710a2fd1a0 upstream. The tv_nsec is a long and when added to the shifted interval it can wrap and become negative which later causes looping problems in the getrawmonotonic(). The edge case occurs when the system has slept for a short period of time of ~2 seconds. A trace printk of the values in this patch illustrate the problem: ftrace time stamp: log 43.716079: logarithmic_accumulation: raw: 3d0913 tv_nsec d687faa 43.718513: logarithmic_accumulation: raw: 3d0913 tv_nsec da588bd 43.722161: logarithmic_accumulation: raw: 3d0913 tv_nsec de291d0 46.349925: logarithmic_accumulation: raw: 7a122600 tv_nsec e1f9ae3 46.349930: logarithmic_accumulation: raw: 1e848980 tv_nsec 8831c0e3 The kernel starts looping at 46.349925 in the getrawmonotonic() due to the negative value from adding the raw value to tv_nsec. A simple solution is to accumulate into a u64, and then normalize it to a timespec_t. Signed-off-by: Jason Wessel [ Reworked variable names and simplified some of the code. - John ] Signed-off-by: John Stultz Cc: Thomas Gleixner Cc: H. Peter Anvin Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/time/timekeeping.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index caf8d4d4f5c8..66038608cb30 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -736,6 +736,7 @@ static void timekeeping_adjust(s64 offset) static cycle_t logarithmic_accumulation(cycle_t offset, int shift) { u64 nsecps = (u64)NSEC_PER_SEC << timekeeper.shift; + u64 raw_nsecs; /* If the offset is smaller then a shifted interval, do nothing */ if (offset < timekeeper.cycle_interval<= NSEC_PER_SEC) { - raw_time.tv_nsec -= NSEC_PER_SEC; + /* Accumulate raw time */ + raw_nsecs = timekeeper.raw_interval << shift; + raw_nsecs += raw_time.tv_nsec; + while (raw_nsecs >= NSEC_PER_SEC) { + raw_nsecs -= NSEC_PER_SEC; raw_time.tv_sec++; } + raw_time.tv_nsec = raw_nsecs; /* Accumulate error between NTP and clock interval */ timekeeper.ntp_error += tick_length << shift; -- cgit v1.2.3 From 59ea469c637e35604a6989a933b33883b1fcb0ab Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 13 Aug 2010 11:30:58 -0700 Subject: time: Workaround gcc loop optimization that causes 64bit div errors commit c7dcf87a6881bf796faee83003163eb3de41a309 upstream. Early 4.3 versions of gcc apparently aggressively optimize the raw time accumulation loop, replacing it with a divide. On 32bit systems, this causes the following link errors: undefined reference to `__umoddi3' undefined reference to `__udivdi3' The gcc issue has been fixed in 4.4 and greater. This patch replaces the accumulation loop with a do_div, as suggested by Linus. Signed-off-by: John Stultz CC: Jason Wessel CC: Larry Finger CC: Ingo Molnar CC: Linus Torvalds Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/time/timekeeping.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 66038608cb30..b87c22f5faf9 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -756,9 +756,10 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift) /* Accumulate raw time */ raw_nsecs = timekeeper.raw_interval << shift; raw_nsecs += raw_time.tv_nsec; - while (raw_nsecs >= NSEC_PER_SEC) { - raw_nsecs -= NSEC_PER_SEC; - raw_time.tv_sec++; + if (raw_nsecs >= NSEC_PER_SEC) { + u64 raw_secs = raw_nsecs; + raw_nsecs = do_div(raw_secs, NSEC_PER_SEC); + raw_time.tv_sec += raw_secs; } raw_time.tv_nsec = raw_nsecs; -- cgit v1.2.3 From a5f18b1cca50987eb7773bb0be0d8730dfb10306 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 3 Aug 2010 00:31:48 -0700 Subject: can-raw: Fix skb_orphan_try handling commit cff0d6e6edac7672b3f915bb4fb59f279243b7f9 upstream. Commit fc6055a5ba31e2c14e36e8939f9bf2b6d586a7f5 (net: Introduce skb_orphan_try()) allows an early orphan of the skb and takes care on tx timestamping, which needs the sk-reference in the skb on driver level. So does the can-raw socket, which has not been taken into account here. The patch below adds a 'prevent_sk_orphan' bit in the skb tx shared info, which fixes the problem discovered by Matthias Fuchs here: http://marc.info/?t=128030411900003&r=1&w=2 Even if it's not a primary tx timestamp topic it fits well into some skb shared tx context. Or should be find a different place for the information to protect the sk reference until it reaches the driver level? Signed-off-by: Oliver Hartkopp Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/skbuff.h | 4 +++- net/can/raw.c | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index f89e7fd59a4c..eb674b783d43 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -169,6 +169,7 @@ struct skb_shared_hwtstamps { * @software: generate software time stamp * @in_progress: device driver is going to provide * hardware time stamp + * @prevent_sk_orphan: make sk reference available on driver level * @flags: all shared_tx flags * * These flags are attached to packets as part of the @@ -178,7 +179,8 @@ union skb_shared_tx { struct { __u8 hardware:1, software:1, - in_progress:1; + in_progress:1, + prevent_sk_orphan:1; }; __u8 flags; }; diff --git a/net/can/raw.c b/net/can/raw.c index da99cf153b33..1650599f995f 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -655,6 +655,10 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock, err = sock_tx_timestamp(msg, sk, skb_tx(skb)); if (err < 0) goto free_skb; + + /* to be able to check the received tx sock reference in raw_rcv() */ + skb_tx(skb)->prevent_sk_orphan = 1; + skb->dev = dev; skb->sk = sk; -- cgit v1.2.3 From 3ee378d7e0dfdb9bb342f59067d0d83cec9b766e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 9 Aug 2010 10:57:02 -0700 Subject: iwlagn: fix rts cts protection This is a backport of mainline commit 94597ab23ea10b3bdcba534be00a9f7b35791c07. I removed the variable renamings from it and made it apply on 2.6.35. It now also incorporates some changes from commit cfecc6b492162fb49209a83dc207f182b87ea27a since those were required as well. commit 94597ab23ea10b3bdcba534be00a9f7b35791c07 upstream. Currently the driver will try to protect all frames, which leads to a lot of odd things like sending an RTS with a zeroed RA before multicast frames, which is clearly bogus. In order to fix all of this, we need to take a step back and see what we need to achieve: * we need RTS/CTS protection if requested by the AP for the BSS, mac80211 tells us this * in that case, CTS-to-self should only be enabled when mac80211 tells us * additionally, as a hardware workaround, on some devices we have to protect aggregated frames with RTS To achieve the first two items, set up the RXON accordingly and set the protection required flag in the transmit command when mac80211 requests protection for the frame. To achieve the last item, set the rate-control RTS-requested flag for all stations that we have aggregation sessions with, and set the protection required flag when sending aggregated frames (on those devices where this is required). Since otherwise bugs can occur, do not allow the user to override the RTS-for-aggregation setting from sysfs any more. Finally, also clean up the way all these flags get set in the driver and move everything into the device-specific functions. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-3945.c | 16 ------------ drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 17 ++++++++++--- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 17 ++++--------- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 20 +-------------- drivers/net/wireless/iwlwifi/iwl-agn.c | 38 ++++++++++++++++++++++------- drivers/net/wireless/iwlwifi/iwl-core.c | 25 +++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl-core.h | 10 +++++--- drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 +--- 8 files changed, 79 insertions(+), 69 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index c44a303e62ed..2a9480dab2d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -915,22 +915,6 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, rts_retry_limit = data_retry_limit; tx_cmd->rts_retry_limit = rts_retry_limit; - if (ieee80211_is_mgmt(fc)) { - switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { - case cpu_to_le16(IEEE80211_STYPE_AUTH): - case cpu_to_le16(IEEE80211_STYPE_DEAUTH): - case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): - case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): - if (tx_flags & TX_CMD_FLG_RTS_MSK) { - tx_flags &= ~TX_CMD_FLG_RTS_MSK; - tx_flags |= TX_CMD_FLG_CTS_MSK; - } - break; - default: - break; - } - } - tx_cmd->rate = rate; tx_cmd->tx_flags = tx_flags; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 01658cf82d39..2a30397ced7d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -209,10 +209,21 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) } } -static void iwlagn_rts_tx_cmd_flag(struct ieee80211_tx_info *info, - __le32 *tx_flags) +static void iwlagn_rts_tx_cmd_flag(struct iwl_priv *priv, + struct ieee80211_tx_info *info, + __le16 fc, __le32 *tx_flags) { - *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS || + info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { + *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; + return; + } + + if (priv->cfg->use_rts_for_ht && + info->flags & IEEE80211_TX_CTL_AMPDU) { + *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; + return; + } } /* Calc max signal level (dBm) among 3 possible receivers */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index cf4a95bae4ff..ca468312aaf3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -325,18 +325,11 @@ static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, struct iwl_lq_sta *lq_data, struct ieee80211_sta *sta) { - if ((tid < TID_MAX_LOAD_COUNT) && - !rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta)) { - if (priv->cfg->use_rts_for_ht) { - /* - * switch to RTS/CTS if it is the prefer protection - * method for HT traffic - */ - IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n"); - priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; - iwlcore_commit_rxon(priv); - } - } + if (tid < TID_MAX_LOAD_COUNT) + rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); + else + IWL_ERR(priv, "tid exceeds max load count: %d/%d\n", + tid, TID_MAX_LOAD_COUNT); } static inline int get_num_of_ant_from_rate(u32 rate_n_flags) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 7d614c4d3c62..3a3d27c20c42 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -376,10 +376,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; } - priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); - - if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) - tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; + priv->cfg->ops->utils->rts_tx_cmd_flag(priv, info, fc, &tx_flags); tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); if (ieee80211_is_mgmt(fc)) { @@ -453,21 +450,6 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) rate_flags |= RATE_MCS_CCK_MSK; - /* Set up RTS and CTS flags for certain packets */ - switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { - case cpu_to_le16(IEEE80211_STYPE_AUTH): - case cpu_to_le16(IEEE80211_STYPE_DEAUTH): - case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): - case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): - if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) { - tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK; - tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK; - } - break; - default: - break; - } - /* Set up antennas */ priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 24aff654fa9c..21b03af52aea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -200,13 +200,6 @@ int iwl_commit_rxon(struct iwl_priv *priv) priv->start_calib = 0; if (new_assoc) { - /* - * allow CTS-to-self if possible for new association. - * this is relevant only for 5000 series and up, - * but will not damage 4965 - */ - priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN; - /* Apply the new configuration * RXON assoc doesn't clear the station table in uCode, */ @@ -3336,13 +3329,40 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", priv->_agn.agg_tids_count); } + if (priv->cfg->use_rts_for_ht) { + struct iwl_station_priv *sta_priv = + (void *) sta->drv_priv; + /* + * switch off RTS/CTS if it was previously enabled + */ + + sta_priv->lq_sta.lq.general_params.flags &= + ~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; + iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq, + CMD_ASYNC, false); + } + break; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return 0; else return ret; case IEEE80211_AMPDU_TX_OPERATIONAL: - /* do nothing */ - return -EOPNOTSUPP; + if (priv->cfg->use_rts_for_ht) { + struct iwl_station_priv *sta_priv = + (void *) sta->drv_priv; + + /* + * switch to RTS/CTS if it is the prefer protection + * method for HT traffic + */ + + sta_priv->lq_sta.lq.general_params.flags |= + LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; + iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq, + CMD_ASYNC, false); + } + ret = 0; + break; default: IWL_DEBUG_HT(priv, "unknown\n"); return -EINVAL; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 5bbc5298ef96..3d4b650fabce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -403,19 +403,36 @@ EXPORT_SYMBOL(iwlcore_free_geos); * iwlcore_rts_tx_cmd_flag: Set rts/cts. 3945 and 4965 only share this * function. */ -void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info, - __le32 *tx_flags) +void iwlcore_rts_tx_cmd_flag(struct iwl_priv *priv, + struct ieee80211_tx_info *info, + __le16 fc, __le32 *tx_flags) { if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { *tx_flags |= TX_CMD_FLG_RTS_MSK; *tx_flags &= ~TX_CMD_FLG_CTS_MSK; + *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; + + if (!ieee80211_is_mgmt(fc)) + return; + + switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { + case cpu_to_le16(IEEE80211_STYPE_AUTH): + case cpu_to_le16(IEEE80211_STYPE_DEAUTH): + case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): + case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): + *tx_flags &= ~TX_CMD_FLG_RTS_MSK; + *tx_flags |= TX_CMD_FLG_CTS_MSK; + break; + } } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { *tx_flags &= ~TX_CMD_FLG_RTS_MSK; *tx_flags |= TX_CMD_FLG_CTS_MSK; + *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; } } EXPORT_SYMBOL(iwlcore_rts_tx_cmd_flag); + static bool is_single_rx_stream(struct iwl_priv *priv) { return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC || @@ -1936,6 +1953,10 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; + if (bss_conf->use_cts_prot) + priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN; + else + priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; } if (changes & BSS_CHANGED_BASIC_RATES) { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 31775bd9c361..ed4a208d0c3e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -102,8 +102,9 @@ struct iwl_hcmd_utils_ops { u32 min_average_noise, u8 default_chain); void (*chain_noise_reset)(struct iwl_priv *priv); - void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info, - __le32 *tx_flags); + void (*rts_tx_cmd_flag)(struct iwl_priv *priv, + struct ieee80211_tx_info *info, + __le16 fc, __le32 *tx_flags); int (*calc_rssi)(struct iwl_priv *priv, struct iwl_rx_phy_res *rx_resp); void (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif); @@ -375,8 +376,9 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif); void iwl_mac_reset_tsf(struct ieee80211_hw *hw); int iwl_alloc_txq_mem(struct iwl_priv *priv); void iwl_free_txq_mem(struct iwl_priv *priv); -void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info, - __le32 *tx_flags); +void iwlcore_rts_tx_cmd_flag(struct iwl_priv *priv, + struct ieee80211_tx_info *info, + __le16 fc, __le32 *tx_flags); #ifdef CONFIG_IWLWIFI_DEBUGFS int iwl_alloc_traffic_mem(struct iwl_priv *priv); void iwl_free_traffic_mem(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index a27872de4106..0e966fc7c245 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -434,10 +434,7 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; } - priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); - - if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) - tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; + priv->cfg->ops->utils->rts_tx_cmd_flag(priv, info, fc, &tx_flags); tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); if (ieee80211_is_mgmt(fc)) { -- cgit v1.2.3 From 305b06f7334dd43bc952b525d7232f4cae7c3818 Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Thu, 12 Aug 2010 04:13:56 +0100 Subject: dm: separate device deletion from dm_put commit 3f77316de0ec0fd208467fbee8d9edc70e2c73b2 upstream. This patch separates the device deletion code from dm_put() to make sure the deletion happens in the process context. By this patch, device deletion always occurs in an ioctl (process) context and dm_put() can be called in interrupt context. As a result, the request-based dm's bad dm_put() usage pointed out by Mikulas below disappears. http://marc.info/?l=dm-devel&m=126699981019735&w=2 Without this patch, I confirmed there is a case to crash the system: dm_put() => dm_table_destroy() => vfree() => BUG_ON(in_interrupt()) Some more backgrounds and details: In request-based dm, a device opener can remove a mapped_device while the last request is still completing, because bios in the last request complete first and then the device opener can close and remove the mapped_device before the last request completes: CPU0 CPU1 ================================================================= <> blk_end_request_all(clone_rq) blk_update_request(clone_rq) bio_endio(clone_bio) == end_clone_bio blk_update_request(orig_rq) bio_endio(orig_bio) <> dm_blk_close() dev_remove() dm_put(md) <> blk_finish_request(clone_rq) .... dm_end_request(clone_rq) free_rq_clone(clone_rq) blk_end_request_all(orig_rq) rq_completed(md) So request-based dm used dm_get()/dm_put() to hold md for each I/O until its request completion handling is fully done. However, the final dm_put() can call the device deletion code which must not be run in interrupt context and may cause kernel panic. To solve the problem, this patch moves the device deletion code, dm_destroy(), to predetermined places that is actually deleting the mapped_device in ioctl (process) context, and changes dm_put() just to decrement the reference count of the mapped_device. By this change, dm_put() can be used in any context and the symmetric model below is introduced: dm_create(): create a mapped_device dm_destroy(): destroy a mapped_device dm_get(): increment the reference count of a mapped_device dm_put(): decrement the reference count of a mapped_device dm_destroy() waits for all references of the mapped_device to disappear, then deletes the mapped_device. dm_destroy() uses active waiting with msleep(1), since deleting the mapped_device isn't performance-critical task. And since at this point, nobody opens the mapped_device and no new reference will be taken, the pending counts are just for racing completing activity and will eventually decrease to zero. For the unlikely case of the forced module unload, dm_destroy_immediate(), which doesn't wait and forcibly deletes the mapped_device, is also introduced and used in dm_hash_remove_all(). Otherwise, "rmmod -f" may be stuck and never return. And now, because the mapped_device is deleted at this point, subsequent accesses to the mapped_device may cause NULL pointer references. Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-ioctl.c | 6 +++++ drivers/md/dm.c | 62 ++++++++++++++++++++++++++++++++++++++------------- drivers/md/dm.h | 5 +++++ 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index f81c53604141..bb6bdc85232e 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -274,6 +274,10 @@ retry: up_write(&_hash_lock); dm_put(md); + if (likely(keep_open_devices)) + dm_destroy(md); + else + dm_destroy_immediate(md); /* * Some mapped devices may be using other mapped @@ -646,6 +650,7 @@ static int dev_create(struct dm_ioctl *param, size_t param_size) r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md); if (r) { dm_put(md); + dm_destroy(md); return r; } @@ -748,6 +753,7 @@ static int dev_remove(struct dm_ioctl *param, size_t param_size) param->flags |= DM_UEVENT_GENERATED_FLAG; dm_put(md); + dm_destroy(md); return 0; } diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 56d192dbe9f1..e3a512dc593a 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -2176,6 +2177,7 @@ void dm_set_mdptr(struct mapped_device *md, void *ptr) void dm_get(struct mapped_device *md) { atomic_inc(&md->holders); + BUG_ON(test_bit(DMF_FREEING, &md->flags)); } const char *dm_device_name(struct mapped_device *md) @@ -2184,27 +2186,55 @@ const char *dm_device_name(struct mapped_device *md) } EXPORT_SYMBOL_GPL(dm_device_name); -void dm_put(struct mapped_device *md) +static void __dm_destroy(struct mapped_device *md, bool wait) { struct dm_table *map; - BUG_ON(test_bit(DMF_FREEING, &md->flags)); + might_sleep(); - if (atomic_dec_and_lock(&md->holders, &_minor_lock)) { - map = dm_get_live_table(md); - idr_replace(&_minor_idr, MINOR_ALLOCED, - MINOR(disk_devt(dm_disk(md)))); - set_bit(DMF_FREEING, &md->flags); - spin_unlock(&_minor_lock); - if (!dm_suspended_md(md)) { - dm_table_presuspend_targets(map); - dm_table_postsuspend_targets(map); - } - dm_sysfs_exit(md); - dm_table_put(map); - dm_table_destroy(__unbind(md)); - free_dev(md); + spin_lock(&_minor_lock); + map = dm_get_live_table(md); + idr_replace(&_minor_idr, MINOR_ALLOCED, MINOR(disk_devt(dm_disk(md)))); + set_bit(DMF_FREEING, &md->flags); + spin_unlock(&_minor_lock); + + if (!dm_suspended_md(md)) { + dm_table_presuspend_targets(map); + dm_table_postsuspend_targets(map); } + + /* + * Rare, but there may be I/O requests still going to complete, + * for example. Wait for all references to disappear. + * No one should increment the reference count of the mapped_device, + * after the mapped_device state becomes DMF_FREEING. + */ + if (wait) + while (atomic_read(&md->holders)) + msleep(1); + else if (atomic_read(&md->holders)) + DMWARN("%s: Forcibly removing mapped_device still in use! (%d users)", + dm_device_name(md), atomic_read(&md->holders)); + + dm_sysfs_exit(md); + dm_table_put(map); + dm_table_destroy(__unbind(md)); + free_dev(md); +} + +void dm_destroy(struct mapped_device *md) +{ + __dm_destroy(md, true); +} + +void dm_destroy_immediate(struct mapped_device *md) +{ + __dm_destroy(md, false); +} + +void dm_put(struct mapped_device *md) +{ + atomic_dec(&md->holders); } EXPORT_SYMBOL_GPL(dm_put); diff --git a/drivers/md/dm.h b/drivers/md/dm.h index bad1724d4869..8223671e4901 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -122,6 +122,11 @@ void dm_linear_exit(void); int dm_stripe_init(void); void dm_stripe_exit(void); +/* + * mapped_device operations + */ +void dm_destroy(struct mapped_device *md); +void dm_destroy_immediate(struct mapped_device *md); int dm_open_count(struct mapped_device *md); int dm_lock_for_deletion(struct mapped_device *md); -- cgit v1.2.3 From d94b0aa7865743fda22297bc1d34e5e0fe6a6733 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Thu, 19 Aug 2010 15:48:30 -0700 Subject: e1000e: disable ASPM L1 on 82573 commit 19833b5dffe2f2e92a1b377f9aae9d5f32239512 upstream. On the e1000-devel mailing list, Nils Faerber reported latency issues with the 82573 LOM on a ThinkPad X60. It was found to be caused by ASPM L1; disabling it resolves the latency. The issue is present in kernels back to 2.6.34 and possibly 2.6.33. Reported-by: Nils Faerber Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/e1000e/82571.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index f654db9121de..1b3fdedbac58 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -1833,6 +1833,7 @@ struct e1000_info e1000_82573_info = { | FLAG_HAS_SMART_POWER_DOWN | FLAG_HAS_AMT | FLAG_HAS_SWSM_ON_LOAD, + .flags2 = FLAG2_DISABLE_ASPM_L1, .pba = 20, .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, .get_variants = e1000_get_variants_82571, -- cgit v1.2.3 From 654cfa23ae31350403cf3db30b4fa9fa8b5bb5e2 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Thu, 19 Aug 2010 15:48:52 -0700 Subject: e1000e: don't check for alternate MAC addr on parts that don't support it commit 1aef70ef125165e0114a8e475636eff242a52030 upstream. From: Bruce Allan The alternate MAC address feature is only supported by 80003ES2LAN and 82571 LOMs as well as a couple 82571 mezzanine cards. Checking for an alternate MAC address on other parts can fail leading to the driver not able to load. This patch limits the check for an alternate MAC address to be done only for parts that support the feature. This issue has been around since support for the feature was introduced to the e1000e driver in 2.6.34. Signed-off-by: Bruce Allan Reported-by: Fabio Varesano Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/e1000e/82571.c | 30 +++++++++++++++++------------- drivers/net/e1000e/defines.h | 4 ++++ drivers/net/e1000e/lib.c | 10 ++++++++++ 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 1b3fdedbac58..d206f218a803 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -936,12 +936,14 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) ew32(IMC, 0xffffffff); icr = er32(ICR); - /* Install any alternate MAC address into RAR0 */ - ret_val = e1000_check_alt_mac_addr_generic(hw); - if (ret_val) - return ret_val; + if (hw->mac.type == e1000_82571) { + /* Install any alternate MAC address into RAR0 */ + ret_val = e1000_check_alt_mac_addr_generic(hw); + if (ret_val) + return ret_val; - e1000e_set_laa_state_82571(hw, true); + e1000e_set_laa_state_82571(hw, true); + } /* Reinitialize the 82571 serdes link state machine */ if (hw->phy.media_type == e1000_media_type_internal_serdes) @@ -1618,14 +1620,16 @@ static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw) { s32 ret_val = 0; - /* - * If there's an alternate MAC address place it in RAR0 - * so that it will override the Si installed default perm - * address. - */ - ret_val = e1000_check_alt_mac_addr_generic(hw); - if (ret_val) - goto out; + if (hw->mac.type == e1000_82571) { + /* + * If there's an alternate MAC address place it in RAR0 + * so that it will override the Si installed default perm + * address. + */ + ret_val = e1000_check_alt_mac_addr_generic(hw); + if (ret_val) + goto out; + } ret_val = e1000_read_mac_addr_generic(hw); diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index 4dc02c71ffd6..75289ca947de 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -620,6 +620,7 @@ #define E1000_FLASH_UPDATES 2000 /* NVM Word Offsets */ +#define NVM_COMPAT 0x0003 #define NVM_ID_LED_SETTINGS 0x0004 #define NVM_INIT_CONTROL2_REG 0x000F #define NVM_INIT_CONTROL3_PORT_B 0x0014 @@ -642,6 +643,9 @@ /* Mask bits for fields in Word 0x1a of the NVM */ #define NVM_WORD1A_ASPM_MASK 0x000C +/* Mask bits for fields in Word 0x03 of the EEPROM */ +#define NVM_COMPAT_LOM 0x0800 + /* For checksumming, the sum of all words in the NVM should equal 0xBABA. */ #define NVM_SUM 0xBABA diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index a968e3a416ac..768c105ef325 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -183,6 +183,16 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) u16 offset, nvm_alt_mac_addr_offset, nvm_data; u8 alt_mac_addr[ETH_ALEN]; + ret_val = e1000_read_nvm(hw, NVM_COMPAT, 1, &nvm_data); + if (ret_val) + goto out; + + /* Check for LOM (vs. NIC) or one of two valid mezzanine cards */ + if (!((nvm_data & NVM_COMPAT_LOM) || + (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_DUAL) || + (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD))) + goto out; + ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1, &nvm_alt_mac_addr_offset); if (ret_val) { -- cgit v1.2.3 From 637958343c8260d73a81526176286d744d90c317 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 17 Aug 2010 11:24:01 +0200 Subject: iwlwifi: fix 3945 filter flags commit 8b8ab9d5e352aae0dcae53c657b25ab61bb73f0f upstream. Applying the filter flags directly as done since commit 3474ad635db371b0d8d0ee40086f15d223d5b6a4 Author: Johannes Berg Date: Thu Apr 29 04:43:05 2010 -0700 iwlwifi: apply filter flags directly broke 3945 under some unknown circumstances, as reported by Alex. Since I want to keep the direct application of filter flags on iwlagn, duplicate the code into both 3945 and agn and remove committing the RXON that broke things from the 3945 version. Reported-by: Alex Romosan Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-agn.c | 45 ++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-core.c | 45 ------------------------- drivers/net/wireless/iwlwifi/iwl-core.h | 3 -- drivers/net/wireless/iwlwifi/iwl3945-base.c | 51 ++++++++++++++++++++++++++++- 4 files changed, 94 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 21b03af52aea..c7f56b4aeb89 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3443,6 +3443,49 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, return 0; } +static void iwlagn_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) +{ + struct iwl_priv *priv = hw->priv; + __le32 filter_or = 0, filter_nand = 0; + +#define CHK(test, flag) do { \ + if (*total_flags & (test)) \ + filter_or |= (flag); \ + else \ + filter_nand |= (flag); \ + } while (0) + + IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", + changed_flags, *total_flags); + + CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); + CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); + CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); + +#undef CHK + + mutex_lock(&priv->mutex); + + priv->staging_rxon.filter_flags &= ~filter_nand; + priv->staging_rxon.filter_flags |= filter_or; + + iwlcore_commit_rxon(priv); + + mutex_unlock(&priv->mutex); + + /* + * Receiving all multicast frames is always enabled by the + * default flags setup in iwl_connection_init_rx_config() + * since we currently do not support programming multicast + * filters into the device. + */ + *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | + FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; +} + /***************************************************************************** * * driver setup and teardown @@ -3603,7 +3646,7 @@ static struct ieee80211_ops iwl_hw_ops = { .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, .config = iwl_mac_config, - .configure_filter = iwl_configure_filter, + .configure_filter = iwlagn_configure_filter, .set_key = iwl_mac_set_key, .update_tkip_key = iwl_mac_update_tkip_key, .conf_tx = iwl_mac_conf_tx, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 3d4b650fabce..cd5b664e7c34 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1311,51 +1311,6 @@ out: EXPORT_SYMBOL(iwl_apm_init); - -void iwl_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) -{ - struct iwl_priv *priv = hw->priv; - __le32 filter_or = 0, filter_nand = 0; - -#define CHK(test, flag) do { \ - if (*total_flags & (test)) \ - filter_or |= (flag); \ - else \ - filter_nand |= (flag); \ - } while (0) - - IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", - changed_flags, *total_flags); - - CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); - CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); - CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); - -#undef CHK - - mutex_lock(&priv->mutex); - - priv->staging_rxon.filter_flags &= ~filter_nand; - priv->staging_rxon.filter_flags |= filter_or; - - iwlcore_commit_rxon(priv); - - mutex_unlock(&priv->mutex); - - /* - * Receiving all multicast frames is always enabled by the - * default flags setup in iwl_connection_init_rx_config() - * since we currently do not support programming multicast - * filters into the device. - */ - *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | - FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; -} -EXPORT_SYMBOL(iwl_configure_filter); - int iwl_set_hw_params(struct iwl_priv *priv) { priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index ed4a208d0c3e..e8ef31743ad5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -356,9 +356,6 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, u32 decrypt_res, struct ieee80211_rx_status *stats); void iwl_irq_handle_error(struct iwl_priv *priv); -void iwl_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, u64 multicast); int iwl_set_hw_params(struct iwl_priv *priv); void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif); void iwl_bss_info_changed(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 0e966fc7c245..39c0d2db4927 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3462,6 +3462,55 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, return 0; } + +static void iwl3945_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) +{ + struct iwl_priv *priv = hw->priv; + __le32 filter_or = 0, filter_nand = 0; + +#define CHK(test, flag) do { \ + if (*total_flags & (test)) \ + filter_or |= (flag); \ + else \ + filter_nand |= (flag); \ + } while (0) + + IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", + changed_flags, *total_flags); + + CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); + CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); + CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); + +#undef CHK + + mutex_lock(&priv->mutex); + + priv->staging_rxon.filter_flags &= ~filter_nand; + priv->staging_rxon.filter_flags |= filter_or; + + /* + * Committing directly here breaks for some reason, + * but we'll eventually commit the filter flags + * change anyway. + */ + + mutex_unlock(&priv->mutex); + + /* + * Receiving all multicast frames is always enabled by the + * default flags setup in iwl_connection_init_rx_config() + * since we currently do not support programming multicast + * filters into the device. + */ + *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | + FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; +} + + /***************************************************************************** * * sysfs attributes @@ -3867,7 +3916,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, .config = iwl_mac_config, - .configure_filter = iwl_configure_filter, + .configure_filter = iwl3945_configure_filter, .set_key = iwl3945_mac_set_key, .conf_tx = iwl_mac_conf_tx, .reset_tsf = iwl_mac_reset_tsf, -- cgit v1.2.3 From ca3d0a0f66312d45e876ece90c04fc9225bdd3ab Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 16 Aug 2010 11:58:58 +0100 Subject: fixes for using make 3.82 commit 3c955b407a084810f57260d61548cc92c14bc627 upstream. It doesn't like pattern and explicit rules to be on the same line, and it seems to be more picky when matching file (or really directory) names with different numbers of trailing slashes. Signed-off-by: Jan Beulich Acked-by: Sam Ravnborg Andrew Benton Signed-off-by: Michal Marek Signed-off-by: Greg Kroah-Hartman --- firmware/Makefile | 2 +- scripts/mkmakefile | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/firmware/Makefile b/firmware/Makefile index 020e629a615c..99955ed8b198 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -142,7 +142,7 @@ fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-) # Directories which we _might_ need to create, so we have a rule for them. -firmware-dirs := $(sort $(patsubst %,$(objtree)/$(obj)/%/,$(dir $(fw-external-y) $(fw-shipped-all)))) +firmware-dirs := $(sort $(addprefix $(objtree)/$(obj)/,$(dir $(fw-external-y) $(fw-shipped-all)))) quiet_cmd_mkdir = MKDIR $(patsubst $(objtree)/%,%,$@) cmd_mkdir = mkdir -p $@ diff --git a/scripts/mkmakefile b/scripts/mkmakefile index 67d59c7a18dc..5325423ceab4 100644 --- a/scripts/mkmakefile +++ b/scripts/mkmakefile @@ -44,7 +44,9 @@ all: Makefile:; -\$(all) %/: all +\$(all): all @: +%/: all + @: EOF -- cgit v1.2.3 From e7d2aabc6f8b9b465c7f52bb119a89cf9717f817 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Wed, 18 Aug 2010 19:33:43 -0400 Subject: ALSA: intel8x0: Mute External Amplifier by default for ThinkPad X31 commit 9c77b846ec8b4e0c7107dd7f820172462dc84a61 upstream. BugLink: https://bugs.launchpad.net/bugs/619439 This ThinkPad model needs External Amplifier muted for audible playback, so set the inv_eapd quirk for it. Reported-and-tested-by: Dennis Bell Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/intel8x0.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 6433e65c9507..467749249576 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -1774,6 +1774,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "HP/Compaq nx7010", .type = AC97_TUNE_MUTE_LED }, + { + .subvendor = 0x1014, + .subdevice = 0x0534, + .name = "ThinkPad X31", + .type = AC97_TUNE_INV_EAPD + }, { .subvendor = 0x1014, .subdevice = 0x1f00, -- cgit v1.2.3 From 185726c288025a315a5d70984c80d49abb9e115d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 15 Aug 2010 21:20:44 +0000 Subject: netlink: fix compat recvmsg commit 68d6ac6d2740b6a55f3ae92a4e0be6d881904b32 upstream. Since commit 1dacc76d0014a034b8aca14237c127d7c19d7726 Author: Johannes Berg Date: Wed Jul 1 11:26:02 2009 +0000 net/compat/wext: send different messages to compat tasks we had a race condition when setting and then restoring frag_list. Eric attempted to fix it, but the fix created even worse problems. However, the original motivation I had when I added the code that turned out to be racy is no longer clear to me, since we only copy up to skb->len to userspace, which doesn't include the frag_list length. As a result, not doing any frag_list clearing and restoring avoids the race condition, while not introducing any other problems. Additionally, while preparing this patch I found that since none of the remaining netlink code is really aware of the frag_list, we need to use the original skb's information for packet information and credentials. This fixes, for example, the group information received by compat tasks. Cc: Eric Dumazet Signed-off-by: Johannes Berg Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/netlink/af_netlink.c | 46 ++++++++++++++++------------------------------ 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index a2eb965207d3..54d73083cb2a 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1400,7 +1400,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, struct netlink_sock *nlk = nlk_sk(sk); int noblock = flags&MSG_DONTWAIT; size_t copied; - struct sk_buff *skb, *frag __maybe_unused = NULL; + struct sk_buff *skb, *data_skb; int err; if (flags&MSG_OOB) @@ -1412,45 +1412,35 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, if (skb == NULL) goto out; + data_skb = skb; + #ifdef CONFIG_COMPAT_NETLINK_MESSAGES if (unlikely(skb_shinfo(skb)->frag_list)) { - bool need_compat = !!(flags & MSG_CMSG_COMPAT); - /* - * If this skb has a frag_list, then here that means that - * we will have to use the frag_list skb for compat tasks - * and the regular skb for non-compat tasks. + * If this skb has a frag_list, then here that means that we + * will have to use the frag_list skb's data for compat tasks + * and the regular skb's data for normal (non-compat) tasks. * - * The skb might (and likely will) be cloned, so we can't - * just reset frag_list and go on with things -- we need to - * keep that. For the compat case that's easy -- simply get - * a reference to the compat skb and free the regular one - * including the frag. For the non-compat case, we need to - * avoid sending the frag to the user -- so assign NULL but - * restore it below before freeing the skb. + * If we need to send the compat skb, assign it to the + * 'data_skb' variable so that it will be used below for data + * copying. We keep 'skb' for everything else, including + * freeing both later. */ - if (need_compat) { - struct sk_buff *compskb = skb_shinfo(skb)->frag_list; - skb_get(compskb); - kfree_skb(skb); - skb = compskb; - } else { - frag = skb_shinfo(skb)->frag_list; - skb_shinfo(skb)->frag_list = NULL; - } + if (flags & MSG_CMSG_COMPAT) + data_skb = skb_shinfo(skb)->frag_list; } #endif msg->msg_namelen = 0; - copied = skb->len; + copied = data_skb->len; if (len < copied) { msg->msg_flags |= MSG_TRUNC; copied = len; } - skb_reset_transport_header(skb); - err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + skb_reset_transport_header(data_skb); + err = skb_copy_datagram_iovec(data_skb, 0, msg->msg_iov, copied); if (msg->msg_name) { struct sockaddr_nl *addr = (struct sockaddr_nl *)msg->msg_name; @@ -1470,11 +1460,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, } siocb->scm->creds = *NETLINK_CREDS(skb); if (flags & MSG_TRUNC) - copied = skb->len; - -#ifdef CONFIG_COMPAT_NETLINK_MESSAGES - skb_shinfo(skb)->frag_list = frag; -#endif + copied = data_skb->len; skb_free_datagram(sk, skb); -- cgit v1.2.3 From eeba6084bb7f45c3fdedbce67cffd6bcef834ef8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 12 Aug 2010 18:05:34 -0400 Subject: drm/radeon/kms: don't enable MSIs on AGP boards commit da7be684c55dbaeebfc1a048d5faf52d52cb3c1f upstream. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=29327 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_irq_kms.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 059bfa4098d7..a108c7ed14f5 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -121,11 +121,12 @@ int radeon_irq_kms_init(struct radeon_device *rdev) * chips. Disable MSI on them for now. */ if ((rdev->family >= CHIP_RV380) && - (!(rdev->flags & RADEON_IS_IGP))) { + (!(rdev->flags & RADEON_IS_IGP)) && + (!(rdev->flags & RADEON_IS_AGP))) { int ret = pci_enable_msi(rdev->pdev); if (!ret) { rdev->msi_enabled = 1; - DRM_INFO("radeon: using MSI.\n"); + dev_info(rdev->dev, "radeon: using MSI.\n"); } } rdev->irq.installed = true; -- cgit v1.2.3 From 0e485a9e6662219a4458f08c0dce6ff1a7222d8a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 13 Aug 2010 10:53:35 -0400 Subject: drm/radeon/kms/pm: bail early if nothing's changing commit 4e186b2d6c878793587c35d7f06c94565d76e9b8 upstream. If we aren't changing the power state, no need to take locks and schedule fences, etc. There seem to be lock ordering issues in the CP and fence code in some cases; see bug 29140 below. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=29140 Possibly also: https://bugzilla.kernel.org/show_bug.cgi?id=16581 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_pm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 3fa6984d9896..c91b741d5b4f 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -224,6 +224,11 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) { int i; + /* 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) && + (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index)) + return; + mutex_lock(&rdev->ddev->struct_mutex); mutex_lock(&rdev->vram_mutex); mutex_lock(&rdev->cp.mutex); -- cgit v1.2.3 From a9982269c438c05742a58636165700f6fe0c38db Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 17 Aug 2010 00:35:45 -0400 Subject: drm/radeon/kms: fix typo in radeon_compute_pll_gain commit 0537398b211b4f040564beec458e23571042d335 upstream. Looks like this got copied from the ddx wrong. Cc: Benjamin Herrenschmidt Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index e1e5255396ac..cf3a51fc9851 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -272,7 +272,7 @@ static uint8_t radeon_compute_pll_gain(uint16_t ref_freq, uint16_t ref_div, if (!ref_div) return 1; - vcoFreq = ((unsigned)ref_freq & fb_div) / ref_div; + vcoFreq = ((unsigned)ref_freq * fb_div) / ref_div; /* * This is horribly crude: the VCO frequency range is divided into -- cgit v1.2.3 From 410ff49be76bfef96889b1e4718bf1bc2048a636 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 19 Aug 2010 11:19:31 -0400 Subject: drm/radeon/kms/DCE3+: switch pads to ddc mode when going i2c commit 5786e2c5a3f519647c50bbc276e45d36a704415a upstream. The pins for ddc and aux are shared so you need to switch the mode when doing ddc. The ProcessAuxChannel table already sets the pin mode to DP. This should fix unreliable ddc issues on DP ports using non-DP monitors. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_i2c.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 5def6f5dff38..0cd2704e9a48 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -95,6 +95,13 @@ static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state) } } + /* switch the pads to ddc mode */ + if (ASIC_IS_DCE3(rdev) && rec->hw_capable) { + temp = RREG32(rec->mask_clk_reg); + temp &= ~(1 << 16); + WREG32(rec->mask_clk_reg, temp); + } + /* clear the output pin values */ temp = RREG32(rec->a_clk_reg) & ~rec->a_clk_mask; WREG32(rec->a_clk_reg, temp); -- cgit v1.2.3 From 1cc67a626a131a78227db806cb4fa3b557d2c3f7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 20 Aug 2010 12:47:54 -0400 Subject: drm/radeon/kms: fix sideport detection on newer rs880 boards commit 4b80d954a7e54c13a5063af18d01719ad6a0daf3 upstream. The meaning of ucMemoryType changed on recent boards, however, ulBootUpSidePortClock should be set properly across all boards. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_atombios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index a05024959b03..6bfef51bd583 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1059,7 +1059,7 @@ bool radeon_atombios_sideport_present(struct radeon_device *rdev) } break; case 2: - if (igp_info->info_2.ucMemoryType & 0x0f) + if (igp_info->info_2.ulBootUpSidePortClock) return true; break; default: -- cgit v1.2.3 From e617eefb30dd6c1494ff5b4dc51c0217daa70908 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Mon, 16 Aug 2010 11:54:36 -0400 Subject: drm/radeon/kms: fix GTT/VRAM overlapping test commit 2cbeb4efc2b9739fe6019b613ae658bd2119a3eb upstream. GTT/VRAM overlapping test had a typo which leaded to not detecting case when vram_end > gtt_end. This patch fix the logic and should fix #16574 Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index dd279da90546..a7184636dcb4 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -199,7 +199,7 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 mc->mc_vram_size = mc->aper_size; } mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; - if (rdev->flags & RADEON_IS_AGP && mc->vram_end > mc->gtt_start && mc->vram_end <= mc->gtt_end) { + if (rdev->flags & RADEON_IS_AGP && mc->vram_end > mc->gtt_start && mc->vram_start <= mc->gtt_end) { dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); mc->real_vram_size = mc->aper_size; mc->mc_vram_size = mc->aper_size; -- cgit v1.2.3 From cbdd4c098ba34731ceec62c47c36ec8e3d0d252e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 17 Aug 2010 14:46:00 +1000 Subject: drm: stop information leak of old kernel stack. commit b9f0aee83335db1f3915f4e42a5e21b351740afd upstream. non-critical issue, CVE-2010-2803 Userspace controls the amount of memory to be allocate, so it can get the ioctl to allocate more memory than the kernel uses, and get access to kernel stack. This can only be done for processes authenticated to the X server for DRI access, and if the user has DRI access. Fix is to just memset the data to 0 if the user doesn't copy into it in the first place. Reported-by: Kees Cook Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_drv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 4a66201edaec..c9736ed5d5bf 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -502,7 +502,9 @@ long drm_ioctl(struct file *filp, retcode = -EFAULT; goto err_i1; } - } + } else + memset(kdata, 0, _IOC_SIZE(cmd)); + if (ioctl->flags & DRM_UNLOCKED) retcode = func(dev, kdata, file_priv); else { -- cgit v1.2.3 From 37b419b202eaebc97c05e598895ea16cbde112a7 Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Mon, 9 Aug 2010 23:56:39 +0200 Subject: Staging: batman-adv: unify orig_hash_lock spinlock handling to avoid deadlocks commit 9abc10238e1df7ce81c58a441f65efd5e905b9e8 upstream. The orig_hash_lock spinlock always has to be locked with IRQs being disabled to avoid deadlocks between code that is being executed in IRQ context and code that is being executed in non-IRQ context. Reported-by: Sven Eckelmann Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/originator.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index 568aef8371be..2177c5007f10 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c @@ -401,11 +401,12 @@ static int orig_node_add_if(struct orig_node *orig_node, int max_if_num) int orig_hash_add_if(struct batman_if *batman_if, int max_if_num) { struct orig_node *orig_node; + unsigned long flags; HASHIT(hashit); /* resize all orig nodes because orig_node->bcast_own(_sum) depend on * if_num */ - spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags); while (hash_iterate(orig_hash, &hashit)) { orig_node = hashit.bucket->data; @@ -414,11 +415,11 @@ int orig_hash_add_if(struct batman_if *batman_if, int max_if_num) goto err; } - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); return 0; err: - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); return -ENOMEM; } @@ -480,12 +481,13 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num) { struct batman_if *batman_if_tmp; struct orig_node *orig_node; + unsigned long flags; HASHIT(hashit); int ret; /* resize all orig nodes because orig_node->bcast_own(_sum) depend on * if_num */ - spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags); while (hash_iterate(orig_hash, &hashit)) { orig_node = hashit.bucket->data; @@ -512,10 +514,10 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num) rcu_read_unlock(); batman_if->if_num = -1; - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); return 0; err: - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); return -ENOMEM; } -- cgit v1.2.3 From 6e5cab8eac427fd754cc70aba0906228277cdea2 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sat, 21 Aug 2010 14:18:08 +0200 Subject: Staging: batman-adv: Create batman_if only on register event commit 1189f130f89b73eecb6117c0fc5e90abbcb7faa0 upstream. We try to get all events for all net_devices to be able to add special sysfs folders for the batman-adv configuration. This also includes such events like NETDEV_POST_INIT which has no valid kobject according to v2.6.32-rc3-13-g7ffbe3f. This would create an oops in that situation. It is enough to create the batman_if only on NETDEV_REGISTER events because we will also receive those events for devices which already existed when we registered the notifier call. Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/hard-interface.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 7a582e80de18..92997327ae9f 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -397,15 +397,13 @@ static int hard_if_event(struct notifier_block *this, /* FIXME: each batman_if will be attached to a softif */ struct bat_priv *bat_priv = netdev_priv(soft_device); - if (!batman_if) - batman_if = hardif_add_interface(net_dev); + if (!batman_if && event == NETDEV_REGISTER) + batman_if = hardif_add_interface(net_dev); if (!batman_if) goto out; switch (event) { - case NETDEV_REGISTER: - break; case NETDEV_UP: hardif_activate_interface(bat_priv, batman_if); break; -- cgit v1.2.3 From b6c68ad83cbc3bcf4ff83f62340fbf891f44735c Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sat, 21 Aug 2010 14:18:09 +0200 Subject: Staging: batman-adv: Don't use net_dev after dev_put commit 51a00eaf6e008b60943af6ab68c17ac3622208dc upstream. dev_put allows a device to be freed when all its references are dropped. After that we are not allowed to access that information anymore. Access to the data structure of a net_device must be surrounded a dev_hold and ended using dev_put. batman-adv adds a device to its own management structure in hardif_add_interface and will release it in hardif_remove_interface. Thus it must hold a reference all the time between those functions to prevent any access to the already released net_device structure. Reported-by: Tim Glaremin Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/hard-interface.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 92997327ae9f..d108fa1eb733 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -194,8 +194,6 @@ static void hardif_activate_interface(struct bat_priv *bat_priv, if (batman_if->if_status != IF_INACTIVE) return; - dev_hold(batman_if->net_dev); - update_mac_addresses(batman_if); batman_if->if_status = IF_TO_BE_ACTIVATED; @@ -222,8 +220,6 @@ static void hardif_deactivate_interface(struct batman_if *batman_if) (batman_if->if_status != IF_TO_BE_ACTIVATED)) return; - dev_put(batman_if->net_dev); - batman_if->if_status = IF_INACTIVE; printk(KERN_INFO "batman-adv:Interface deactivated: %s\n", @@ -321,12 +317,14 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev) if (ret != 1) goto out; + dev_hold(net_dev); + batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC); if (!batman_if) { printk(KERN_ERR "batman-adv:" "Can't add interface (%s): out of memory\n", net_dev->name); - goto out; + goto release_dev; } batman_if->dev = kstrdup(net_dev->name, GFP_ATOMIC); @@ -350,6 +348,8 @@ free_dev: kfree(batman_if->dev); free_if: kfree(batman_if); +release_dev: + dev_put(net_dev); out: return NULL; } @@ -378,6 +378,7 @@ static void hardif_remove_interface(struct batman_if *batman_if) batman_if->if_status = IF_TO_BE_REMOVED; list_del_rcu(&batman_if->list); sysfs_del_hardif(&batman_if->hardif_obj); + dev_put(batman_if->net_dev); call_rcu(&batman_if->rcu, hardif_free_interface); } -- cgit v1.2.3 From 964505fabe0410e11cc5487a9a4b17dbec461ffd Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sat, 21 Aug 2010 14:18:10 +0200 Subject: Staging: batman-adv: Don't write in not allocated packet_buff commit f86b9984250fa2b71ce36d4693a939a58579583b upstream. Each net_device in a system will automatically managed as a possible batman_if and holds different informations like a buffer with a prepared originator messages. To reduce the memory usage, the packet_buff will only be allocated when the interface is really added/enabled for batman-adv. The function to update the hw address information inside the packet_buff just assumes that the packet_buff is always initialised and thus the kernel will just oops when we try to change the hw address of a not already fully enabled interface. We must always check if the packet_buff is allocated before we try to change information inside of it. Reported-by: Tim Glaremin Reported-by: Kazuki Shimada Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/hard-interface.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index d108fa1eb733..ce1d2512047c 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -128,6 +128,9 @@ static bool hardif_is_iface_up(struct batman_if *batman_if) static void update_mac_addresses(struct batman_if *batman_if) { + if (!batman_if || !batman_if->packet_buff) + return; + addr_to_string(batman_if->addr_str, batman_if->net_dev->dev_addr); memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig, @@ -338,6 +341,7 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev) batman_if->if_num = -1; batman_if->net_dev = net_dev; batman_if->if_status = IF_NOT_IN_USE; + batman_if->packet_buff = NULL; INIT_LIST_HEAD(&batman_if->list); check_known_mac_addr(batman_if->net_dev->dev_addr); -- cgit v1.2.3 From 680dc8e519bdbd1ad0c6ffb51d5fdc9d52f5b923 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Sun, 15 Aug 2010 22:26:56 +0000 Subject: powerpc: Fix typo in uImage target commit c686ecf5040d287a68d4fca7f1948472f556a6d3 upstream. Commit e32e78c5ee8aadef020fbaecbe6fb741ed9029fd (powerpc: fix build with make 3.82) introduced a typo in uImage target and broke building uImage: make: *** No rule to make target `uImage'. Stop. Signed-off-by: Anatolij Gustschin Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 5d2f17dcb728..b2e363537bc5 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -164,7 +164,7 @@ drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ all: zImage # With make 3.82 we cannot mix normal and wildcard targets -BOOT_TARGETS1 := zImage zImage.initrd uImaged +BOOT_TARGETS1 := zImage zImage.initrd uImage BOOT_TARGETS2 := zImage% dtbImage% treeImage.% cuImage.% simpleImage.% PHONY += $(BOOT_TARGETS1) $(BOOT_TARGETS2) -- cgit v1.2.3 From 51f663a00e62c08701fa74e53ece1bdfbf08fad7 Mon Sep 17 00:00:00 2001 From: Michael Tokarev Date: Fri, 6 Aug 2010 18:49:21 +0400 Subject: USB: option: add Celot CT-650 commit 76078dc4fc389185fe467d33428f259ea9e69807 upstream. Signed-off-by: Michael Tokarev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5c35b3a7082a..80c74d46c133 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -368,6 +368,10 @@ static void option_instat_callback(struct urb *urb); #define OLIVETTI_VENDOR_ID 0x0b3c #define OLIVETTI_PRODUCT_OLICARD100 0xc000 +/* Celot products */ +#define CELOT_VENDOR_ID 0x211f +#define CELOT_PRODUCT_CT680M 0x6801 + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -891,10 +895,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F) }, { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)}, { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)}, - { USB_DEVICE(CINTERION_VENDOR_ID, 0x0047) }, - { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, + { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); -- cgit v1.2.3 From e60577f8ff1f00807cbd78a8eeab21cdd7161b42 Mon Sep 17 00:00:00 2001 From: Ross Burton Date: Fri, 6 Aug 2010 16:36:39 +0100 Subject: USB: add device IDs for igotu to navman commit 0eee6a2b2a52e17066a572d30ad2805d3ebc7508 upstream. I recently bought a i-gotU USB GPS, and whilst hunting around for linux support discovered this post by you back in 2009: http://kerneltrap.org/mailarchive/linux-usb/2009/3/12/5148644 >Try the navman driver instead. You can either add the device id to the > driver and rebuild it, or do this before you plug the device in: > modprobe navman > echo -n "0x0df7 0x0900" > /sys/bus/usb-serial/drivers/navman/new_id > > and then plug your device in and see if that works. I can confirm that the navman driver works with the right device IDs on my i-gotU GT-600, which has the same device IDs. Attached is a patch adding the IDs. From: Ross Burton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/navman.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index a6b207c84917..1f00f243c26c 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c @@ -25,6 +25,7 @@ static int debug; static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0a99, 0x0001) }, /* Talon Technology device */ + { USB_DEVICE(0x0df7, 0x0900) }, /* Mobile Action i-gotU */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); -- cgit v1.2.3 From a848012ab324c13aff0836d5778cdc6423013938 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 9 Aug 2010 15:55:32 +0200 Subject: USB: pl2303: New vendor and product id commit f36ecd5de93e4c85a9e3d25100c6e233155b12e5 upstream. Add support for the Zeagle N2iTiON3 dive computer interface. Since Zeagle devices are actually manufactured by Seiko, this patch will support other Seiko based models as well. Signed-off-by: Jef Driesen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 1 + drivers/usb/serial/pl2303.h | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 6b6001822279..c98f0fb675ba 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -86,6 +86,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, + { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) }, { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) }, diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index a871645389dd..43eb9bdad422 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -128,6 +128,10 @@ #define CRESSI_VENDOR_ID 0x04b8 #define CRESSI_EDY_PRODUCT_ID 0x0521 +/* Zeagle dive computer interface */ +#define ZEAGLE_VENDOR_ID 0x04b8 +#define ZEAGLE_N2ITION3_PRODUCT_ID 0x0522 + /* Sony, USB data cable for CMD-Jxx mobile phones */ #define SONY_VENDOR_ID 0x054c #define SONY_QN3USB_PRODUCT_ID 0x0437 -- cgit v1.2.3 From cdead9a39eb906aa6fde0996f5274f42c603b259 Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Wed, 18 Aug 2010 22:13:39 +0100 Subject: USB: CP210x Fix Break On/Off commit 72916791cbeb9cc607ae620cfba207dea481cd76 upstream. The definitions for BREAK_ON and BREAK_OFF are inverted, causing break requests to fail. This patch sets BREAK_ON and BREAK_OFF to the correct values. Signed-off-by: Craig Shelley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 2bef4415c19c..80bf8333bb03 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -222,8 +222,8 @@ static struct usb_serial_driver cp210x_device = { #define BITS_STOP_2 0x0002 /* CP210X_SET_BREAK */ -#define BREAK_ON 0x0000 -#define BREAK_OFF 0x0001 +#define BREAK_ON 0x0001 +#define BREAK_OFF 0x0000 /* CP210X_(SET_MHS|GET_MDMSTS) */ #define CONTROL_DTR 0x0001 -- cgit v1.2.3 From 5ce775be7b38ee371c389b28efebca141fabc133 Mon Sep 17 00:00:00 2001 From: Michael Wileczka Date: Wed, 18 Aug 2010 07:14:37 -0700 Subject: USB: ftdi_sio: fix endianess of max packet size commit d1ab903d2552b2362339b19203c7f01c797cb316 upstream. The USB max packet size (always little-endian) was not being byte swapped on big-endian systems. Applicable since [USB: ftdi_sio: fix hi-speed device packet size calculation] approx 2.6.31 Signed-off-by: Michael Wileczka Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index eb12d9b096b4..e04a41613fbf 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1376,7 +1376,7 @@ static void ftdi_set_max_packet_size(struct usb_serial_port *port) } /* set max packet size based on descriptor */ - priv->max_packet_size = ep_desc->wMaxPacketSize; + priv->max_packet_size = le16_to_cpu(ep_desc->wMaxPacketSize); dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size); } -- cgit v1.2.3 From e5af095003749e3f9bc1ff3db77ef7c91dc79459 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 17 Aug 2010 15:15:37 -0700 Subject: USB: io_ti: check firmware version before updating commit 0827a9ff2bbcbb03c33f1a6eb283fe051059482c upstream. If we can't read the firmware for a device from the disk, and yet the device already has a valid firmware image in it, we don't want to replace the firmware with something invalid. So check the version number to be less than the current one to verify this is the correct thing to do. Reported-by: Chris Beauchamp Tested-by: Chris Beauchamp Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 0fca2659206f..99910632c6c3 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -1151,7 +1151,7 @@ static int download_fw(struct edgeport_serial *serial) /* Check if we have an old version in the I2C and update if necessary */ - if (download_cur_ver != download_new_ver) { + if (download_cur_ver < download_new_ver) { dbg("%s - Update I2C dld from %d.%d to %d.%d", __func__, firmware_version->Ver_Major, -- cgit v1.2.3 From ba6da120819f5ffc44cbb5a66fc70f1e9f2f858e Mon Sep 17 00:00:00 2001 From: John Youn Date: Mon, 9 Aug 2010 13:56:11 -0700 Subject: USB: xhci: Remove buggy assignment in next_trb() commit a1669b2c64a9c8b031e0ac5cbf2692337a577f7c upstream. The code to increment the TRB pointer has a slight ambiguity that could lead to a bug on different compilers. The ANSI C specification does not specify the precedence of the assignment operator over the postfix operator. gcc 4.4 produced the correct code (increment the pointer and assign the value), but a MIPS compiler that one of John's clients used assigned the old (unincremented) value. Remove the unnecessary assignment to make all compilers produce the correct assembly. Signed-off-by: John Youn Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index bfc99a939455..221f99930dc3 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -131,7 +131,7 @@ static void next_trb(struct xhci_hcd *xhci, *seg = (*seg)->next; *trb = ((*seg)->trbs); } else { - *trb = (*trb)++; + (*trb)++; } } -- cgit v1.2.3 From a305c4c5dd114443b4612b3a82811aa63845f741 Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Tue, 10 Aug 2010 20:31:21 +0100 Subject: USB: ftdi_sio: Add ID for Ionics PlugComputer commit 666cc076d284e32d11bfc5ea2fbfc50434cff051 upstream. Add the ID for the Ionics PlugComputer (). Signed-off-by: Martin Michlmayr 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(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index e04a41613fbf..aeb93316791a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -750,6 +750,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) }, + { USB_DEVICE(IONICS_VID, IONICS_PLUGCOMPUTER_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 6e612c52e763..aa37cc511282 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -988,6 +988,12 @@ #define ALTI2_VID 0x1BC9 #define ALTI2_N3_PID 0x6001 /* Neptune 3 */ +/* + * Ionics PlugComputer + */ +#define IONICS_VID 0x1c0c +#define IONICS_PLUGCOMPUTER_PID 0x0102 + /* * Dresden Elektronik Sensor Terminal Board */ -- cgit v1.2.3 From a87da791eaa200a75a47fabc4a39eaa32e42deca Mon Sep 17 00:00:00 2001 From: Galen Seitz Date: Thu, 19 Aug 2010 11:15:20 -0700 Subject: USB: ftdi_sio: add product ID for Lenz LI-USB commit ea233f805537f5da16c2b34d85b6c5cf88a0f9aa upstream. Add ftdi product ID for Lenz LI-USB, a model train interface. This was NOT tested against 2.6.35, but a similar patch was tested with the CentOS 2.6.18-194.11.1.el5 kernel. It wasn't clear to me what ordering is being used in ftdi_sio.c, so I inserted the ID after another model train entry(SPROG_II). Signed-off-by: Galen Seitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index aeb93316791a..63ddb2f65cee 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -180,6 +180,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, + { USB_DEVICE(FTDI_VID, FTDI_LENZ_LIUSB_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index aa37cc511282..2e95857c9633 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -110,6 +110,9 @@ /* Propox devices */ #define FTDI_PROPOX_JTAGCABLEII_PID 0xD738 +/* Lenz LI-USB Computer Interface. */ +#define FTDI_LENZ_LIUSB_PID 0xD780 + /* * Xsens Technologies BV products (http://www.xsens.com). */ -- cgit v1.2.3 From f5d76aba51998b28810ae026a30577bd8d2abae5 Mon Sep 17 00:00:00 2001 From: Tim Chen Date: Wed, 18 Aug 2010 15:00:27 -0700 Subject: mutex: Improve the scalability of optimistic spinning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 9d0f4dcc5c4d1c5dd01172172684a45b5f49d740 upstream. There is a scalability issue for current implementation of optimistic mutex spin in the kernel. It is found on a 8 node 64 core Nehalem-EX system (HT mode). The intention of the optimistic mutex spin is to busy wait and spin on a mutex if the owner of the mutex is running, in the hope that the mutex will be released soon and be acquired, without the thread trying to acquire mutex going to sleep. However, when we have a large number of threads, contending for the mutex, we could have the mutex grabbed by other thread, and then another ……, and we will keep spinning, wasting cpu cycles and adding to the contention. One possible fix is to quit spinning and put the current thread on wait-list if mutex lock switch to a new owner while we spin, indicating heavy contention (see the patch included). I did some testing on a 8 socket Nehalem-EX system with a total of 64 cores. Using Ingo's test-mutex program that creates/delete files with 256 threads (http://lkml.org/lkml/2006/1/8/50) , I see the following speed up after putting in the mutex spin fix: ./mutex-test V 256 10 Ops/sec 2.6.34 62864 With fix 197200 Repeating the test with Aim7 fserver workload, again there is a speed up with the fix: Jobs/min 2.6.34 91657 With fix 149325 To look at the impact on the distribution of mutex acquisition time, I collected the mutex acquisition time on Aim7 fserver workload with some instrumentation. The average acquisition time is reduced by 48% and number of contentions reduced by 32%. #contentions Time to acquire mutex (cycles) 2.6.34 72973 44765791 With fix 49210 23067129 The histogram of mutex acquisition time is listed below. The acquisition time is in 2^bin cycles. We see that without the fix, the acquisition time is mostly around 2^26 cycles. With the fix, we the distribution get spread out a lot more towards the lower cycles, starting from 2^13. However, there is an increase of the tail distribution with the fix at 2^28 and 2^29 cycles. It seems a small price to pay for the reduced average acquisition time and also getting the cpu to do useful work. Mutex acquisition time distribution (acq time = 2^bin cycles): 2.6.34 With Fix bin #occurrence % #occurrence % 11 2 0.00% 120 0.24% 12 10 0.01% 790 1.61% 13 14 0.02% 2058 4.18% 14 86 0.12% 3378 6.86% 15 393 0.54% 4831 9.82% 16 710 0.97% 4893 9.94% 17 815 1.12% 4667 9.48% 18 790 1.08% 5147 10.46% 19 580 0.80% 6250 12.70% 20 429 0.59% 6870 13.96% 21 311 0.43% 1809 3.68% 22 255 0.35% 2305 4.68% 23 317 0.44% 916 1.86% 24 610 0.84% 233 0.47% 25 3128 4.29% 95 0.19% 26 63902 87.69% 122 0.25% 27 619 0.85% 286 0.58% 28 0 0.00% 3536 7.19% 29 0 0.00% 903 1.83% 30 0 0.00% 0 0.00% I've done similar experiments with 2.6.35 kernel on smaller boxes as well. One is on a dual-socket Westmere box (12 cores total, with HT). Another experiment is on an old dual-socket Core 2 box (4 cores total, no HT) On the 12-core Westmere box, I see a 250% increase for Ingo's mutex-test program with my mutex patch but no significant difference in aim7's fserver workload. On the 4-core Core 2 box, I see the difference with the patch for both mutex-test and aim7 fserver are negligible. So far, it seems like the patch has not caused regression on smaller systems. Signed-off-by: Tim Chen Acked-by: Peter Zijlstra Cc: Linus Torvalds Cc: Andrew Morton Cc: Thomas Gleixner Cc: Frederic Weisbecker LKML-Reference: <1282168827.9542.72.camel@schen9-DESK> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/kernel/sched.c b/kernel/sched.c index 63b4a14682fa..6d0dbebc2d7f 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3694,8 +3694,16 @@ int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner) /* * Owner changed, break to re-assess state. */ - if (lock->owner != owner) + if (lock->owner != owner) { + /* + * If the lock has switched to a different owner, + * we likely have heavy contention. Return 0 to quit + * optimistic spinning and not contend further: + */ + if (lock->owner) + return 0; break; + } /* * Is that owner really running on that cpu? -- cgit v1.2.3 From bdf6e8eb218794850dfff2e2858590fda91e7f36 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Wed, 18 Aug 2010 15:33:13 -0700 Subject: tracing: Fix timer tracing commit ede1b4290781ae82ccf0f2ecc6dada8d3dd35779 upstream. PowerTOP would like to be able to trace timers. Unfortunately, the current timer tracing is not very useful: the actual timer function is not recorded in the trace at the start of timer execution. Although this is recorded for timer "start" time (when it gets armed), this is not useful; most timers get started early, and a tracer like PowerTOP will never see this event, but will only see the actual running of the timer. This patch just adds the function to the timer tracing; I've verified with PowerTOP that now it can get useful information about timers. Signed-off-by: Arjan van de Ven Cc: xiaoguangrong@cn.fujitsu.com Cc: Steven Rostedt Cc: Frederic Weisbecker Cc: Peter Zijlstra LKML-Reference: <4C6C5FA9.3000405@linux.intel.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- include/trace/events/timer.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h index 9496b965d62a..fa8223ab95fb 100644 --- a/include/trace/events/timer.h +++ b/include/trace/events/timer.h @@ -74,14 +74,16 @@ TRACE_EVENT(timer_expire_entry, TP_STRUCT__entry( __field( void *, timer ) __field( unsigned long, now ) + __field( void *, function) ), TP_fast_assign( __entry->timer = timer; __entry->now = jiffies; + __entry->function = timer->function; ), - TP_printk("timer=%p now=%lu", __entry->timer, __entry->now) + TP_printk("timer=%p function=%pf now=%lu", __entry->timer, __entry->function,__entry->now) ); /** @@ -213,14 +215,16 @@ TRACE_EVENT(hrtimer_expire_entry, TP_STRUCT__entry( __field( void *, hrtimer ) __field( s64, now ) + __field( void *, function) ), TP_fast_assign( __entry->hrtimer = hrtimer; __entry->now = now->tv64; + __entry->function = hrtimer->function; ), - TP_printk("hrtimer=%p now=%llu", __entry->hrtimer, + TP_printk("hrtimer=%p function=%pf now=%llu", __entry->hrtimer, __entry->function, (unsigned long long)ktime_to_ns((ktime_t) { .tv64 = __entry->now })) ); -- cgit v1.2.3 From 1506707a6c740db316e422239a53ae5df1727591 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 26 Aug 2010 16:47:12 -0700 Subject: Linux 2.6.35.4 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 554683d03919..73ab03326440 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 35 -EXTRAVERSION = .3 +EXTRAVERSION = .4 NAME = Sheep on Meth # *DOCUMENTATION* -- cgit v1.2.3 From b3f69c04298fecbd5ca382679bac644433771dae Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 25 Aug 2010 15:42:10 +0200 Subject: hwmon: (ads7871) Fix ads7871_probe error paths commit c12c507d7185fe4e8ada7ed9832957576eefecf8 upstream. 1. remove 'status' variable 2. remove unneeded initialization of 'err' variable 3. return missing error code if sysfs_create_group fail. 4. fix the init sequence as: - check hardware existence - kzalloc for ads7871_data - sysfs_create_group - hwmon_device_register Signed-off-by: Axel Lin Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/ads7871.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c index b300a2048af1..52319340e182 100644 --- a/drivers/hwmon/ads7871.c +++ b/drivers/hwmon/ads7871.c @@ -160,30 +160,12 @@ static const struct attribute_group ads7871_group = { static int __devinit ads7871_probe(struct spi_device *spi) { - int status, ret, err = 0; + int ret, err; uint8_t val; struct ads7871_data *pdata; dev_dbg(&spi->dev, "probe\n"); - pdata = kzalloc(sizeof(struct ads7871_data), GFP_KERNEL); - if (!pdata) { - err = -ENOMEM; - goto exit; - } - - status = sysfs_create_group(&spi->dev.kobj, &ads7871_group); - if (status < 0) - goto error_free; - - pdata->hwmon_dev = hwmon_device_register(&spi->dev); - if (IS_ERR(pdata->hwmon_dev)) { - err = PTR_ERR(pdata->hwmon_dev); - goto error_remove; - } - - spi_set_drvdata(spi, pdata); - /* Configure the SPI bus */ spi->mode = (SPI_MODE_0); spi->bits_per_word = 8; @@ -201,6 +183,24 @@ static int __devinit ads7871_probe(struct spi_device *spi) we need to make sure we really have a chip*/ if (val != ret) { err = -ENODEV; + goto exit; + } + + pdata = kzalloc(sizeof(struct ads7871_data), GFP_KERNEL); + if (!pdata) { + err = -ENOMEM; + goto exit; + } + + err = sysfs_create_group(&spi->dev.kobj, &ads7871_group); + if (err < 0) + goto error_free; + + spi_set_drvdata(spi, pdata); + + pdata->hwmon_dev = hwmon_device_register(&spi->dev); + if (IS_ERR(pdata->hwmon_dev)) { + err = PTR_ERR(pdata->hwmon_dev); goto error_remove; } -- cgit v1.2.3 From 4427834682c11181af9627b99beabbe38f0830be Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Wed, 25 Aug 2010 15:42:12 +0200 Subject: hwmon: (k8temp) Differentiate between AM2 and ASB1 commit a05e93f3b3fc2f53c1d0de3b17019e207c482349 upstream. Commit 8bf0223ed515be24de0c671eedaff49e78bebc9c (hwmon, k8temp: Fix temperature reporting for ASB1 processor revisions) fixed temperature reporting for ASB1 CPUs. But those CPU models (model 0x6b, 0x6f, 0x7f) were packaged both as AM2 (desktop) and ASB1 (mobile). Thus the commit leads to wrong temperature reporting for AM2 CPU parts. The solution is to determine the package type for models 0x6b, 0x6f, 0x7f. This is done using BrandId from CPUID Fn8000_0001_EBX[15:0]. See "Constructing the processor Name String" in "Revision Guide for AMD NPT Family 0Fh Processors" (Rev. 3.46). Cc: Rudolf Marek Reported-by: Vladislav Guberinic Signed-off-by: Andreas Herrmann Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/k8temp.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c index 8bdf80d91598..8364932fa20b 100644 --- a/drivers/hwmon/k8temp.c +++ b/drivers/hwmon/k8temp.c @@ -143,6 +143,37 @@ static const struct pci_device_id k8temp_ids[] = { MODULE_DEVICE_TABLE(pci, k8temp_ids); +static int __devinit is_rev_g_desktop(u8 model) +{ + u32 brandidx; + + if (model < 0x69) + return 0; + + if (model == 0xc1 || model == 0x6c || model == 0x7c) + return 0; + + /* + * Differentiate between AM2 and ASB1. + * See "Constructing the processor Name String" in "Revision + * Guide for AMD NPT Family 0Fh Processors" (33610). + */ + brandidx = cpuid_ebx(0x80000001); + brandidx = (brandidx >> 9) & 0x1f; + + /* Single core */ + if ((model == 0x6f || model == 0x7f) && + (brandidx == 0x7 || brandidx == 0x9 || brandidx == 0xc)) + return 0; + + /* Dual core */ + if (model == 0x6b && + (brandidx == 0xb || brandidx == 0xc)) + return 0; + + return 1; +} + static int __devinit k8temp_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -179,9 +210,7 @@ static int __devinit k8temp_probe(struct pci_dev *pdev, "wrong - check erratum #141\n"); } - if ((model >= 0x69) && - !(model == 0xc1 || model == 0x6c || model == 0x7c || - model == 0x6b || model == 0x6f || model == 0x7f)) { + if (is_rev_g_desktop(model)) { /* * RevG desktop CPUs (i.e. no socket S1G1 or * ASB1 parts) need additional offset, -- cgit v1.2.3 From 62b1700a2d04d5a5a8a506b7c604be9bd0b5ca79 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 20 Aug 2010 19:10:01 -0700 Subject: xen: handle events as edge-triggered commit dffe2e1e1a1ddb566a76266136c312801c66dcf7 upstream. Xen events are logically edge triggered, as Xen only calls the event upcall when an event is newly set, but not continuously as it remains set. As a result, use handle_edge_irq rather than handle_level_irq. This has the important side-effect of fixing a long-standing bug of events getting lost if: - an event's interrupt handler is running - the event is migrated to a different vcpu - the event is re-triggered The most noticable symptom of these lost events is occasional lockups of blkfront. Many thanks to Tom Kopec and Daniel Stodden in tracking this down. Signed-off-by: Jeremy Fitzhardinge Cc: Tom Kopec Cc: Daniel Stodden Signed-off-by: Greg Kroah-Hartman --- drivers/xen/events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 28f133ae76ad..cc72dad34ded 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -363,7 +363,7 @@ int bind_evtchn_to_irq(unsigned int evtchn) irq = find_unbound_irq(); set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, - handle_level_irq, "event"); + handle_edge_irq, "event"); evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_evtchn_info(evtchn); -- cgit v1.2.3 From fb412a178502dc498430723b082a932f797e4763 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 20 Aug 2010 18:57:53 -0700 Subject: xen: use percpu interrupts for IPIs and VIRQs commit aaca49642b92c8a57d3ca5029a5a94019c7af69f upstream. IPIs and VIRQs are inherently per-cpu event types, so treat them as such: - use a specific percpu irq_chip implementation, and - handle them with handle_percpu_irq This makes the path for delivering these interrupts more efficient (no masking/unmasking, no locks), and it avoid problems with attempts to migrate them. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- drivers/xen/events.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index cc72dad34ded..14ed3582025a 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -107,6 +107,7 @@ static inline unsigned long *cpu_evtchn_mask(int cpu) #define VALID_EVTCHN(chn) ((chn) != 0) static struct irq_chip xen_dynamic_chip; +static struct irq_chip xen_percpu_chip; /* Constructor for packed IRQ information. */ static struct irq_info mk_unbound_info(void) @@ -389,8 +390,8 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) if (irq < 0) goto out; - set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, - handle_level_irq, "ipi"); + set_irq_chip_and_handler_name(irq, &xen_percpu_chip, + handle_percpu_irq, "ipi"); bind_ipi.vcpu = cpu; if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, @@ -430,8 +431,8 @@ static int bind_virq_to_irq(unsigned int virq, unsigned int cpu) irq = find_unbound_irq(); - set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, - handle_level_irq, "virq"); + set_irq_chip_and_handler_name(irq, &xen_percpu_chip, + handle_percpu_irq, "virq"); evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_virq_info(evtchn, virq); @@ -934,6 +935,16 @@ static struct irq_chip xen_dynamic_chip __read_mostly = { .retrigger = retrigger_dynirq, }; +static struct irq_chip en_percpu_chip __read_mostly = { + .name = "xen-percpu", + + .disable = disable_dynirq, + .mask = disable_dynirq, + .unmask = enable_dynirq, + + .ack = ack_dynirq, +}; + void __init xen_init_IRQ(void) { int i; -- cgit v1.2.3 From cf4f5ceca8d72ee794410cb26dc4b64b11d4965f Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 24 Aug 2010 11:42:30 +1000 Subject: xfs: fix untrusted inode number lookup commit 4536f2ad8b330453d7ebec0746c4374eadd649b1 upstream. Commit 7124fe0a5b619d65b739477b3b55a20bf805b06d ("xfs: validate untrusted inode numbers during lookup") changes the inode lookup code to do btree lookups for untrusted inode numbers. This change made an invalid assumption about the alignment of inodes and hence incorrectly calculated the first inode in the cluster. As a result, some inode numbers were being incorrectly considered invalid when they were actually valid. The issue was not picked up by the xfstests suite because it always runs fsr and dump (the two utilities that utilise the bulkstat interface) on cache hot inodes and hence the lookup code in the cold cache path was not sufficiently exercised to uncover this intermittent problem. Fix the issue by relaxing the btree lookup criteria and then checking if the record returned contains the inode number we are lookup for. If it we get an incorrect record, then the inode number is invalid. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_ialloc.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index c7142a064c48..eb779affaaaa 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -1217,7 +1217,6 @@ xfs_imap_lookup( struct xfs_inobt_rec_incore rec; struct xfs_btree_cur *cur; struct xfs_buf *agbp; - xfs_agino_t startino; int error; int i; @@ -1231,13 +1230,13 @@ xfs_imap_lookup( } /* - * derive and lookup the exact inode record for the given agino. If the - * record cannot be found, then it's an invalid inode number and we - * should abort. + * Lookup the inode record for the given agino. If the record cannot be + * found, then it's an invalid inode number and we should abort. Once + * we have a record, we need to ensure it contains the inode number + * we are looking up. */ cur = xfs_inobt_init_cursor(mp, tp, agbp, agno); - startino = agino & ~(XFS_IALLOC_INODES(mp) - 1); - error = xfs_inobt_lookup(cur, startino, XFS_LOOKUP_EQ, &i); + error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i); if (!error) { if (i) error = xfs_inobt_get_rec(cur, &rec, &i); @@ -1250,6 +1249,11 @@ xfs_imap_lookup( if (error) return error; + /* check that the returned record contains the required inode */ + if (rec.ir_startino > agino || + rec.ir_startino + XFS_IALLOC_INODES(mp) <= agino) + return EINVAL; + /* for untrusted inodes check it is allocated first */ if ((flags & XFS_IGET_UNTRUSTED) && (rec.ir_free & XFS_INOBT_MASK(agino - rec.ir_startino))) -- cgit v1.2.3 From efa1f7cba7a728169b7c797dc66cab2a9d8526de Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 24 Aug 2010 11:42:41 +1000 Subject: xfs: ensure we mark all inodes in a freed cluster XFS_ISTALE commit 5b3eed756cd37255cad1181bd86bfd0977e97953 upstream. Under heavy load parallel metadata loads (e.g. dbench), we can fail to mark all the inodes in a cluster being freed as XFS_ISTALE as we skip inodes we cannot get the XFS_ILOCK_EXCL or the flush lock on. When this happens and the inode cluster buffer has already been marked stale and freed, inode reclaim can try to write the inode out as it is dirty and not marked stale. This can result in writing th metadata to an freed extent, or in the case it has already been overwritten trigger a magic number check failure and return an EUCLEAN error such as: Filesystem "ram0": inode 0x442ba1 background reclaim flush failed with 117 Fix this by ensuring that we hoover up all in memory inodes in the cluster and mark them XFS_ISTALE when freeing the cluster. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_inode.c | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index b76a829d7e20..f70221820a12 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1927,6 +1927,11 @@ xfs_iunlink_remove( return 0; } +/* + * A big issue when freeing the inode cluster is is that we _cannot_ skip any + * inodes that are in memory - they all must be marked stale and attached to + * the cluster buffer. + */ STATIC void xfs_ifree_cluster( xfs_inode_t *free_ip, @@ -1958,8 +1963,6 @@ xfs_ifree_cluster( } for (j = 0; j < nbufs; j++, inum += ninodes) { - int found = 0; - blkno = XFS_AGB_TO_DADDR(mp, XFS_INO_TO_AGNO(mp, inum), XFS_INO_TO_AGBNO(mp, inum)); @@ -1978,7 +1981,9 @@ xfs_ifree_cluster( /* * Walk the inodes already attached to the buffer and mark them * stale. These will all have the flush locks held, so an - * in-memory inode walk can't lock them. + * in-memory inode walk can't lock them. By marking them all + * stale first, we will not attempt to lock them in the loop + * below as the XFS_ISTALE flag will be set. */ lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *); while (lip) { @@ -1990,11 +1995,11 @@ xfs_ifree_cluster( &iip->ili_flush_lsn, &iip->ili_item.li_lsn); xfs_iflags_set(iip->ili_inode, XFS_ISTALE); - found++; } lip = lip->li_bio_list; } + /* * For each inode in memory attempt to add it to the inode * buffer and set it up for being staled on buffer IO @@ -2006,6 +2011,7 @@ xfs_ifree_cluster( * even trying to lock them. */ for (i = 0; i < ninodes; i++) { +retry: read_lock(&pag->pag_ici_lock); ip = radix_tree_lookup(&pag->pag_ici_root, XFS_INO_TO_AGINO(mp, (inum + i))); @@ -2016,38 +2022,36 @@ xfs_ifree_cluster( continue; } - /* don't try to lock/unlock the current inode */ + /* + * Don't try to lock/unlock the current inode, but we + * _cannot_ skip the other inodes that we did not find + * in the list attached to the buffer and are not + * already marked stale. If we can't lock it, back off + * and retry. + */ if (ip != free_ip && !xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { read_unlock(&pag->pag_ici_lock); - continue; + delay(1); + goto retry; } read_unlock(&pag->pag_ici_lock); - if (!xfs_iflock_nowait(ip)) { - if (ip != free_ip) - xfs_iunlock(ip, XFS_ILOCK_EXCL); - continue; - } - + xfs_iflock(ip); xfs_iflags_set(ip, XFS_ISTALE); - if (xfs_inode_clean(ip)) { - ASSERT(ip != free_ip); - xfs_ifunlock(ip); - xfs_iunlock(ip, XFS_ILOCK_EXCL); - continue; - } + /* + * we don't need to attach clean inodes or those only + * with unlogged changes (which we throw away, anyway). + */ iip = ip->i_itemp; - if (!iip) { - /* inode with unlogged changes only */ + if (!iip || xfs_inode_clean(ip)) { ASSERT(ip != free_ip); ip->i_update_core = 0; xfs_ifunlock(ip); xfs_iunlock(ip, XFS_ILOCK_EXCL); continue; } - found++; iip->ili_last_fields = iip->ili_format.ilf_fields; iip->ili_format.ilf_fields = 0; @@ -2063,8 +2067,7 @@ xfs_ifree_cluster( xfs_iunlock(ip, XFS_ILOCK_EXCL); } - if (found) - xfs_trans_stale_inode_buf(tp, bp); + xfs_trans_stale_inode_buf(tp, bp); xfs_trans_binval(tp, bp); } -- cgit v1.2.3 From 5beda62ad5ad32189e1e872afb5cc7cbedfcd6fb Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Mon, 23 Aug 2010 08:14:35 +0200 Subject: ALSA: hda - Add Sony VAIO quirk for ALC269 commit dbbcbc073ad3132bfbc410b11546b2fb4bdf2568 upstream. The attached patch enables playback on a Sony VAIO machine. BugLink: http://launchpad.net/bugs/618271 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6d9a5424c265..d84daae2602c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -14244,6 +14244,7 @@ static const struct alc_fixup alc269_fixups[] = { static struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), + SND_PCI_QUIRK(0x104d, 0x9077, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), {} }; -- cgit v1.2.3 From ba106dfd9692193e4406ced6314c57762a5c7520 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 10 Aug 2010 09:18:00 +0200 Subject: ALSA: HDA: Use model=auto for LG R510 commit 81cd3fca642cecb40a1ccef099799dcb5730734b upstream. Two users report model=auto is needed to make the internal mic work properly. BugLink: https://bugs.launchpad.net/bugs/495134 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d84daae2602c..150f45071d3d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -13305,7 +13305,6 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = { SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA), SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER), SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1), - SND_PCI_QUIRK(0x1854, 0x1775, "LG R510", ALC268_DELL), {} }; -- cgit v1.2.3 From d518262124b8577550865a6a82ea25be4ef40ac1 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Thu, 29 Jul 2010 14:46:42 +0200 Subject: ALSA: hda - Rename iMic to Int Mic on Lenovo NB0763 commit 150b432f448281d5518f5229d240923f9a9c5459 upstream. The non-standard name "iMic" makes PulseAudio ignore the microphone. BugLink: https://launchpad.net/bugs/605101 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 150f45071d3d..1a7dfdae3c49 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7005,7 +7005,7 @@ static struct hda_input_mux alc883_lenovo_nb0763_capture_source = { .num_items = 4, .items = { { "Mic", 0x0 }, - { "iMic", 0x1 }, + { "Int Mic", 0x1 }, { "Line", 0x2 }, { "CD", 0x4 }, }, @@ -8575,8 +8575,8 @@ static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = { HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), { } /* end */ }; -- cgit v1.2.3 From 53c51d4aeb274e26155cfff8e09f0aad32f667a0 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Fri, 20 Aug 2010 10:13:16 -0400 Subject: libata-sff: remove harmful BUG_ON from ata_bmdma_qc_issue commit 55ee67f837882f28a900705a2ca1af257ab6c53d upstream. Remove harmful BUG_ON() from ata_bmdma_qc_issue(), as it casts too wide of a net and breaks sata_mv. It also crashes the kernel while doing the BUG_ON(). There's already a WARN_ON_ONCE() further down to catch the case of POLLING for a BMDMA operation. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-sff.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index efa4a18cfb9d..494eb9f1329f 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -2735,10 +2735,6 @@ unsigned int ata_bmdma_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - /* see ata_dma_blacklisted() */ - BUG_ON((ap->flags & ATA_FLAG_PIO_POLLING) && - qc->tf.protocol == ATAPI_PROT_DMA); - /* defer PIO handling to sff_qc_issue */ if (!ata_is_dma(qc->tf.protocol)) return ata_sff_qc_issue(qc); -- cgit v1.2.3 From 004c068df2ac250553936de1833c59b6294e266b Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Thu, 19 Aug 2010 21:40:44 -0400 Subject: sata_mv: fix broken DSM/TRIM support (v2) commit 44b733809a5aba7f6b15a548d31a56d25bf3851c upstream. Fix DSM/TRIM commands in sata_mv (v2). These need to be issued using old-school "BM DMA", rather than via the EDMA host queue. Since the chips don't have proper BM DMA status, we need to be more careful with setting the ATA_DMA_INTR bit, since DSM/TRIM often has a long delay between "DMA complete" and "command complete". GEN_I chips don't have BM DMA, so no TRIM for them. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/sata_mv.c | 44 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index a476cd99b95d..d57f6eb81a35 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1898,19 +1898,25 @@ static void mv_bmdma_start(struct ata_queued_cmd *qc) * LOCKING: * Inherited from caller. */ -static void mv_bmdma_stop(struct ata_queued_cmd *qc) +static void mv_bmdma_stop_ap(struct ata_port *ap) { - struct ata_port *ap = qc->ap; void __iomem *port_mmio = mv_ap_base(ap); u32 cmd; /* clear start/stop bit */ cmd = readl(port_mmio + BMDMA_CMD); - cmd &= ~ATA_DMA_START; - writelfl(cmd, port_mmio + BMDMA_CMD); + if (cmd & ATA_DMA_START) { + cmd &= ~ATA_DMA_START; + writelfl(cmd, port_mmio + BMDMA_CMD); + + /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ + ata_sff_dma_pause(ap); + } +} - /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ - ata_sff_dma_pause(ap); +static void mv_bmdma_stop(struct ata_queued_cmd *qc) +{ + mv_bmdma_stop_ap(qc->ap); } /** @@ -1934,8 +1940,21 @@ static u8 mv_bmdma_status(struct ata_port *ap) reg = readl(port_mmio + BMDMA_STATUS); if (reg & ATA_DMA_ACTIVE) status = ATA_DMA_ACTIVE; - else + else if (reg & ATA_DMA_ERR) status = (reg & ATA_DMA_ERR) | ATA_DMA_INTR; + else { + /* + * Just because DMA_ACTIVE is 0 (DMA completed), + * this does _not_ mean the device is "done". + * So we should not yet be signalling ATA_DMA_INTR + * in some cases. Eg. DSM/TRIM, and perhaps others. + */ + mv_bmdma_stop_ap(ap); + if (ioread8(ap->ioaddr.altstatus_addr) & ATA_BUSY) + status = 0; + else + status = ATA_DMA_INTR; + } return status; } @@ -1995,6 +2014,9 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) switch (tf->protocol) { case ATA_PROT_DMA: + if (tf->command == ATA_CMD_DSM) + return; + /* fall-thru */ case ATA_PROT_NCQ: break; /* continue below */ case ATA_PROT_PIO: @@ -2094,6 +2116,8 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc) if ((tf->protocol != ATA_PROT_DMA) && (tf->protocol != ATA_PROT_NCQ)) return; + if (tf->command == ATA_CMD_DSM) + return; /* use bmdma for this */ /* Fill in Gen IIE command request block */ if (!(tf->flags & ATA_TFLAG_WRITE)) @@ -2289,6 +2313,12 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) switch (qc->tf.protocol) { case ATA_PROT_DMA: + if (qc->tf.command == ATA_CMD_DSM) { + if (!ap->ops->bmdma_setup) /* no bmdma on GEN_I */ + return AC_ERR_OTHER; + break; /* use bmdma for this */ + } + /* fall thru */ case ATA_PROT_NCQ: mv_start_edma(ap, port_mmio, pp, qc->tf.protocol); pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK; -- cgit v1.2.3 From 480a3d4a3bd4f645c8d5139fc65922be14ba09fa Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 17 Aug 2010 14:13:42 +0200 Subject: pata_cmd64x: revert commit d62f5576 commit aba8a08ded89a74f1ba04ae94ecc98f26e27d41c upstream. Commit d62f5576 (pata_cmd64x: fix handling of address setup timings) incorrectly called ata_timing_compute() on UDMA mode on 0 @UT leading to devide by zero fault. Revert it until better fix is available. This is reported in bko#16607 by Milan Kocian who also root caused it. https://bugzilla.kernel.org/show_bug.cgi?id=16607 Signed-off-by: Tejun Heo Reported-and-root-caused-by: Milan Kocian Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/pata_cmd64x.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index 9f5da1c7454b..905ff76d3cbb 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c @@ -121,14 +121,8 @@ static void cmd64x_set_timing(struct ata_port *ap, struct ata_device *adev, u8 m if (pair) { struct ata_timing tp; - ata_timing_compute(pair, pair->pio_mode, &tp, T, 0); ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP); - if (pair->dma_mode) { - ata_timing_compute(pair, pair->dma_mode, - &tp, T, 0); - ata_timing_merge(&tp, &t, &t, ATA_TIMING_SETUP); - } } } -- cgit v1.2.3 From 6d09dba30dfb88cd8bd3c73d09e4c4209bfd1847 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 24 Aug 2010 11:44:34 +1000 Subject: writeback: write_cache_pages doesn't terminate at nr_to_write <= 0 commit 546a1924224078c6f582e68f890b05b387b42653 upstream. I noticed XFS writeback in 2.6.36-rc1 was much slower than it should have been. Enabling writeback tracing showed: flush-253:16-8516 [007] 1342952.351608: wbc_writepage: bdi 253:16: towrt=1024 skip=0 mode=0 kupd=0 bgrd=1 reclm=0 cyclic=1 more=0 older=0x0 start=0x0 end=0x0 flush-253:16-8516 [007] 1342952.351654: wbc_writepage: bdi 253:16: towrt=1023 skip=0 mode=0 kupd=0 bgrd=1 reclm=0 cyclic=1 more=0 older=0x0 start=0x0 end=0x0 flush-253:16-8516 [000] 1342952.369520: wbc_writepage: bdi 253:16: towrt=0 skip=0 mode=0 kupd=0 bgrd=1 reclm=0 cyclic=1 more=0 older=0x0 start=0x0 end=0x0 flush-253:16-8516 [000] 1342952.369542: wbc_writepage: bdi 253:16: towrt=-1 skip=0 mode=0 kupd=0 bgrd=1 reclm=0 cyclic=1 more=0 older=0x0 start=0x0 end=0x0 flush-253:16-8516 [000] 1342952.369549: wbc_writepage: bdi 253:16: towrt=-2 skip=0 mode=0 kupd=0 bgrd=1 reclm=0 cyclic=1 more=0 older=0x0 start=0x0 end=0x0 Writeback is not terminating in background writeback if ->writepage is returning with wbc->nr_to_write == 0, resulting in sub-optimal single page writeback on XFS. Fix the write_cache_pages loop to terminate correctly when this situation occurs and so prevent this sub-optimal background writeback pattern. This improves sustained sequential buffered write performance from around 250MB/s to 750MB/s for a 100GB file on an XFS filesystem on my 8p test VM. Signed-off-by: Dave Chinner Reviewed-by: Wu Fengguang Reviewed-by: Christoph Hellwig Signed-off-by: Greg Kroah-Hartman --- mm/page-writeback.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 37498ef61548..582cba18ae02 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -949,22 +949,16 @@ continue_unlock: } } - if (wbc->nr_to_write > 0) { - if (--wbc->nr_to_write == 0 && - wbc->sync_mode == WB_SYNC_NONE) { - /* - * We stop writing back only if we are - * not doing integrity sync. In case of - * integrity sync we have to keep going - * because someone may be concurrently - * dirtying pages, and we might have - * synced a lot of newly appeared dirty - * pages, but have not synced all of the - * old dirty pages. - */ - done = 1; - break; - } + /* + * We stop writing back only if we are not doing + * integrity sync. In case of integrity sync we have to + * keep going until we have written all the pages + * we tagged for writeback prior to entering this loop. + */ + if (--wbc->nr_to_write <= 0 && + wbc->sync_mode == WB_SYNC_NONE) { + done = 1; + break; } } pagevec_release(&pvec); -- cgit v1.2.3 From de9711df2a891af562936c1eafb3c2e25121c213 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 19 Aug 2010 17:03:38 -0700 Subject: x86, tsc, sched: Recompute cyc2ns_offset's during resume from sleep states commit cd7240c0b900eb6d690ccee088a6c9b46dae815a upstream. TSC's get reset after suspend/resume (even on cpu's with invariant TSC which runs at a constant rate across ACPI P-, C- and T-states). And in some systems BIOS seem to reinit TSC to arbitrary large value (still sync'd across cpu's) during resume. This leads to a scenario of scheduler rq->clock (sched_clock_cpu()) less than rq->age_stamp (introduced in 2.6.32). This leads to a big value returned by scale_rt_power() and the resulting big group power set by the update_group_power() is causing improper load balancing between busy and idle cpu's after suspend/resume. This resulted in multi-threaded workloads (like kernel-compilation) go slower after suspend/resume cycle on core i5 laptops. Fix this by recomputing cyc2ns_offset's during resume, so that sched_clock() continues from the point where it was left off during suspend. Reported-by: Florian Pritz Signed-off-by: Suresh Siddha Signed-off-by: Peter Zijlstra LKML-Reference: <1282262618.2675.24.camel@sbsiddha-MOBL3.sc.intel.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/tsc.h | 2 ++ arch/x86/kernel/tsc.c | 38 ++++++++++++++++++++++++++++++++++++++ arch/x86/power/cpu.c | 2 ++ 3 files changed, 42 insertions(+) diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h index c0427295e8f5..1ca132fc0d03 100644 --- a/arch/x86/include/asm/tsc.h +++ b/arch/x86/include/asm/tsc.h @@ -59,5 +59,7 @@ extern void check_tsc_sync_source(int cpu); extern void check_tsc_sync_target(void); extern int notsc_setup(char *); +extern void save_sched_clock_state(void); +extern void restore_sched_clock_state(void); #endif /* _ASM_X86_TSC_H */ diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 9faf91ae1841..c65f74152473 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -626,6 +626,44 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu) local_irq_restore(flags); } +static unsigned long long cyc2ns_suspend; + +void save_sched_clock_state(void) +{ + if (!sched_clock_stable) + return; + + cyc2ns_suspend = sched_clock(); +} + +/* + * Even on processors with invariant TSC, TSC gets reset in some the + * ACPI system sleep states. And in some systems BIOS seem to reinit TSC to + * arbitrary value (still sync'd across cpu's) during resume from such sleep + * states. To cope up with this, recompute the cyc2ns_offset for each cpu so + * that sched_clock() continues from the point where it was left off during + * suspend. + */ +void restore_sched_clock_state(void) +{ + unsigned long long offset; + unsigned long flags; + int cpu; + + if (!sched_clock_stable) + return; + + local_irq_save(flags); + + get_cpu_var(cyc2ns_offset) = 0; + offset = cyc2ns_suspend - sched_clock(); + + for_each_possible_cpu(cpu) + per_cpu(cyc2ns_offset, cpu) = offset; + + local_irq_restore(flags); +} + #ifdef CONFIG_CPU_FREQ /* Frequency scaling support. Adjust the TSC based timer when the cpu frequency diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c index 1290ba54b350..9c57cb1b33f1 100644 --- a/arch/x86/power/cpu.c +++ b/arch/x86/power/cpu.c @@ -113,6 +113,7 @@ static void __save_processor_state(struct saved_context *ctxt) void save_processor_state(void) { __save_processor_state(&saved_context); + save_sched_clock_state(); } #ifdef CONFIG_X86_32 EXPORT_SYMBOL(save_processor_state); @@ -229,6 +230,7 @@ static void __restore_processor_state(struct saved_context *ctxt) void restore_processor_state(void) { __restore_processor_state(&saved_context); + restore_sched_clock_state(); } #ifdef CONFIG_X86_32 EXPORT_SYMBOL(restore_processor_state); -- cgit v1.2.3 From 133aa6cbaf169f375a70d0ed8df7bc2ab583cc34 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Wed, 25 Aug 2010 21:06:32 +0000 Subject: perf, x86, Pentium4: Clear the P4_CCCR_FORCE_OVF flag commit 8d330919927ea31fa083b5a80084dc991da813a0 upstream. If on Pentium4 CPUs the FORCE_OVF flag is set then an NMI happens on every event, which can generate a flood of NMIs. Clear it. Reported-by: Vince Weaver Signed-off-by: Lin Ming Signed-off-by: Cyrill Gorcunov Cc: Frederic Weisbecker Cc: Peter Zijlstra Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/perf_event_p4.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index 0ffe19e9373a..a187365d98b4 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -457,6 +457,8 @@ static int p4_hw_config(struct perf_event *event) event->hw.config |= event->attr.config & (p4_config_pack_escr(P4_ESCR_MASK_HT) | p4_config_pack_cccr(P4_CCCR_MASK_HT)); + + event->hw.config &= ~P4_CCCR_FORCE_OVF; } rc = x86_setup_perfctr(event); -- cgit v1.2.3 From aa7fe1f4b6b1380162c10676676abdc29fdb4461 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 23 Aug 2010 14:41:22 -0700 Subject: netfilter: fix CONFIG_COMPAT support commit cca77b7c81876d819a5806f408b3c29b5b61a815 upstream. commit f3c5c1bfd430858d3a05436f82c51e53104feb6b (netfilter: xtables: make ip_tables reentrant) forgot to also compute the jumpstack size in the compat handlers. Result is that "iptables -I INPUT -j userchain" turns into -j DROP. Reported by Sebastian Roesner on #netfilter, closes http://bugzilla.netfilter.org/show_bug.cgi?id=669. Note: arptables change is compile-tested only. Signed-off-by: Florian Westphal Acked-by: Eric Dumazet Tested-by: Mikael Pettersson Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/netfilter/arp_tables.c | 3 +++ net/ipv4/netfilter/ip_tables.c | 3 +++ net/ipv6/netfilter/ip6_tables.c | 3 +++ 3 files changed, 9 insertions(+) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 1ac01b128621..aaab5aafcee8 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -1420,6 +1420,9 @@ static int translate_compat_table(const char *name, if (ret != 0) break; ++i; + if (strcmp(arpt_get_target(iter1)->u.user.name, + XT_ERROR_TARGET) == 0) + ++newinfo->stacksize; } if (ret) { /* diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 4b6c5ca610fc..402ce75432e4 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1747,6 +1747,9 @@ translate_compat_table(struct net *net, if (ret != 0) break; ++i; + if (strcmp(ipt_get_target(iter1)->u.user.name, + XT_ERROR_TARGET) == 0) + ++newinfo->stacksize; } if (ret) { /* diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 9d2d68f0e605..211229887e2c 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1765,6 +1765,9 @@ translate_compat_table(struct net *net, if (ret != 0) break; ++i; + if (strcmp(ip6t_get_target(iter1)->u.user.name, + XT_ERROR_TARGET) == 0) + ++newinfo->stacksize; } if (ret) { /* -- cgit v1.2.3 From fa4dc90c63ad8bd633a082f848c937d0d967d162 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 17 Jun 2010 20:16:36 +0100 Subject: PCI: MSI: Remove unsafe and unnecessary hardware access commit fcd097f31a6ee207cc0c3da9cccd2a86d4334785 upstream. During suspend on an SMP system, {read,write}_msi_msg_desc() may be called to mask and unmask interrupts on a device that is already in a reduced power state. At this point memory-mapped registers including MSI-X tables are not accessible, and config space may not be fully functional either. While a device is in a reduced power state its interrupts are effectively masked and its MSI(-X) state will be restored when it is brought back to D0. Therefore these functions can simply read and write msi_desc::msg for devices not in D0. Further, read_msi_msg_desc() should only ever be used to update a previously written message, so it can always read msi_desc::msg and never needs to touch the hardware. Tested-by: "Michael Chan" Signed-off-by: Ben Hutchings Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 77b68eaf021e..03f04dca9b0c 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -196,30 +196,15 @@ void unmask_msi_irq(unsigned int irq) void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) { struct msi_desc *entry = get_irq_desc_msi(desc); - if (entry->msi_attrib.is_msix) { - void __iomem *base = entry->mask_base + - entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; - msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR); - msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR); - msg->data = readl(base + PCI_MSIX_ENTRY_DATA); - } else { - struct pci_dev *dev = entry->dev; - int pos = entry->msi_attrib.pos; - u16 data; + /* We do not touch the hardware (which may not even be + * accessible at the moment) but return the last message + * written. Assert that this is valid, assuming that + * valid messages are not all-zeroes. */ + BUG_ON(!(entry->msg.address_hi | entry->msg.address_lo | + entry->msg.data)); - pci_read_config_dword(dev, msi_lower_address_reg(pos), - &msg->address_lo); - if (entry->msi_attrib.is_64) { - pci_read_config_dword(dev, msi_upper_address_reg(pos), - &msg->address_hi); - pci_read_config_word(dev, msi_data_reg(pos, 1), &data); - } else { - msg->address_hi = 0; - pci_read_config_word(dev, msi_data_reg(pos, 0), &data); - } - msg->data = data; - } + *msg = entry->msg; } void read_msi_msg(unsigned int irq, struct msi_msg *msg) @@ -232,7 +217,10 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg) void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) { struct msi_desc *entry = get_irq_desc_msi(desc); - if (entry->msi_attrib.is_msix) { + + if (entry->dev->current_state != PCI_D0) { + /* Don't touch the hardware now */ + } else if (entry->msi_attrib.is_msix) { void __iomem *base; base = entry->mask_base + entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; -- cgit v1.2.3 From 339cdb0406b8faae3a8250478059360f32e6a1bf Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 23 Jul 2010 14:56:28 +0100 Subject: PCI: MSI: Restore read_msi_msg_desc(); add get_cached_msi_msg_desc() commit 30da55242818a8ca08583188ebcbaccd283ad4d9 upstream. commit 2ca1af9aa3285c6a5f103ed31ad09f7399fc65d7 "PCI: MSI: Remove unsafe and unnecessary hardware access" changed read_msi_msg_desc() to return the last MSI message written instead of reading it from the device, since it may be called while the device is in a reduced power state. However, the pSeries platform code really does need to read messages from the device, since they are initially written by firmware. Therefore: - Restore the previous behaviour of read_msi_msg_desc() - Add new functions get_cached_msi_msg{,_desc}() which return the last MSI message written - Use the new functions where appropriate Acked-by: Michael Ellerman Signed-off-by: Ben Hutchings Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman --- arch/ia64/kernel/msi_ia64.c | 2 +- arch/ia64/sn/kernel/msi_sn.c | 2 +- arch/x86/kernel/apic/io_apic.c | 2 +- drivers/pci/msi.c | 47 +++++++++++++++++++++++++++++++++++++----- include/linux/msi.h | 2 ++ 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c index 6c8922856049..4a746ea838ff 100644 --- a/arch/ia64/kernel/msi_ia64.c +++ b/arch/ia64/kernel/msi_ia64.c @@ -25,7 +25,7 @@ static int ia64_set_msi_irq_affinity(unsigned int irq, if (irq_prepare_move(irq, cpu)) return -1; - read_msi_msg(irq, &msg); + get_cached_msi_msg(irq, &msg); addr = msg.address_lo; addr &= MSI_ADDR_DEST_ID_MASK; diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c index ebfdd6a9ae1a..0c72dd463831 100644 --- a/arch/ia64/sn/kernel/msi_sn.c +++ b/arch/ia64/sn/kernel/msi_sn.c @@ -175,7 +175,7 @@ static int sn_set_msi_irq_affinity(unsigned int irq, * Release XIO resources for the old MSI PCI address */ - read_msi_msg(irq, &msg); + get_cached_msi_msg(irq, &msg); sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; pdev = sn_pdev->pdi_linux_pcidev; provider = SN_PCIDEV_BUSPROVIDER(pdev); diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 2b18af15b3dd..f1efebaf5510 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -3399,7 +3399,7 @@ static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask) cfg = desc->chip_data; - read_msi_msg_desc(desc, &msg); + get_cached_msi_msg_desc(desc, &msg); msg.data &= ~MSI_DATA_VECTOR_MASK; msg.data |= MSI_DATA_VECTOR(cfg->vector); diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 03f04dca9b0c..cd22d693b59e 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -197,9 +197,46 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) { struct msi_desc *entry = get_irq_desc_msi(desc); - /* We do not touch the hardware (which may not even be - * accessible at the moment) but return the last message - * written. Assert that this is valid, assuming that + BUG_ON(entry->dev->current_state != PCI_D0); + + if (entry->msi_attrib.is_msix) { + void __iomem *base = entry->mask_base + + entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; + + msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR); + msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR); + msg->data = readl(base + PCI_MSIX_ENTRY_DATA); + } else { + struct pci_dev *dev = entry->dev; + int pos = entry->msi_attrib.pos; + u16 data; + + pci_read_config_dword(dev, msi_lower_address_reg(pos), + &msg->address_lo); + if (entry->msi_attrib.is_64) { + pci_read_config_dword(dev, msi_upper_address_reg(pos), + &msg->address_hi); + pci_read_config_word(dev, msi_data_reg(pos, 1), &data); + } else { + msg->address_hi = 0; + pci_read_config_word(dev, msi_data_reg(pos, 0), &data); + } + msg->data = data; + } +} + +void read_msi_msg(unsigned int irq, struct msi_msg *msg) +{ + struct irq_desc *desc = irq_to_desc(irq); + + read_msi_msg_desc(desc, msg); +} + +void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) +{ + struct msi_desc *entry = get_irq_desc_msi(desc); + + /* Assert that the cache is valid, assuming that * valid messages are not all-zeroes. */ BUG_ON(!(entry->msg.address_hi | entry->msg.address_lo | entry->msg.data)); @@ -207,11 +244,11 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) *msg = entry->msg; } -void read_msi_msg(unsigned int irq, struct msi_msg *msg) +void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg) { struct irq_desc *desc = irq_to_desc(irq); - read_msi_msg_desc(desc, msg); + get_cached_msi_msg_desc(desc, msg); } void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) diff --git a/include/linux/msi.h b/include/linux/msi.h index 6991ab5b24d1..91b05c171854 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -14,8 +14,10 @@ struct irq_desc; extern void mask_msi_irq(unsigned int irq); extern void unmask_msi_irq(unsigned int irq); extern void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg); +extern void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg); extern void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg); extern void read_msi_msg(unsigned int irq, struct msi_msg *msg); +extern void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg); extern void write_msi_msg(unsigned int irq, struct msi_msg *msg); struct msi_desc { -- cgit v1.2.3 From 1ee3a461df139a0dc8642d951a41507fd80df30c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 18 Jul 2010 21:17:09 +0000 Subject: direct-io: move aio_complete into ->end_io commit 40e2e97316af6e62affab7a392e792494b8d9dde upstream. Filesystems with unwritten extent support must not complete an AIO request until the transaction to convert the extent has been commited. That means the aio_complete calls needs to be moved into the ->end_io callback so that the filesystem can control when to call it exactly. This makes a bit of a mess out of dio_complete and the ->end_io callback prototype even more complicated. Signed-off-by: Christoph Hellwig Reviewed-by: Jan Kara Signed-off-by: Alex Elder Cc: Chuck Ebbert Signed-off-by: Greg Kroah-Hartman --- fs/direct-io.c | 26 ++++++++++++++------------ fs/ext4/inode.c | 10 +++++++--- fs/ocfs2/aops.c | 7 ++++++- fs/xfs/linux-2.6/xfs_aops.c | 7 ++++++- fs/xfs/linux-2.6/xfs_aops.h | 2 ++ include/linux/fs.h | 3 ++- 6 files changed, 37 insertions(+), 18 deletions(-) diff --git a/fs/direct-io.c b/fs/direct-io.c index 7600aacf531d..a10cb91cadea 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -218,7 +218,7 @@ static struct page *dio_get_page(struct dio *dio) * filesystems can use it to hold additional state between get_block calls and * dio_complete. */ -static int dio_complete(struct dio *dio, loff_t offset, int ret) +static int dio_complete(struct dio *dio, loff_t offset, int ret, bool is_async) { ssize_t transferred = 0; @@ -239,14 +239,6 @@ static int dio_complete(struct dio *dio, loff_t offset, int ret) transferred = dio->i_size - offset; } - if (dio->end_io && dio->result) - dio->end_io(dio->iocb, offset, transferred, - dio->map_bh.b_private); - - if (dio->flags & DIO_LOCKING) - /* lockdep: non-owner release */ - up_read_non_owner(&dio->inode->i_alloc_sem); - if (ret == 0) ret = dio->page_errors; if (ret == 0) @@ -254,6 +246,17 @@ static int dio_complete(struct dio *dio, loff_t offset, int ret) if (ret == 0) ret = transferred; + if (dio->end_io && dio->result) { + dio->end_io(dio->iocb, offset, transferred, + dio->map_bh.b_private, ret, is_async); + } else if (is_async) { + aio_complete(dio->iocb, ret, 0); + } + + if (dio->flags & DIO_LOCKING) + /* lockdep: non-owner release */ + up_read_non_owner(&dio->inode->i_alloc_sem); + return ret; } @@ -277,8 +280,7 @@ static void dio_bio_end_aio(struct bio *bio, int error) spin_unlock_irqrestore(&dio->bio_lock, flags); if (remaining == 0) { - int ret = dio_complete(dio, dio->iocb->ki_pos, 0); - aio_complete(dio->iocb, ret, 0); + dio_complete(dio, dio->iocb->ki_pos, 0, true); kfree(dio); } } @@ -1126,7 +1128,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, spin_unlock_irqrestore(&dio->bio_lock, flags); if (ret2 == 0) { - ret = dio_complete(dio, offset, ret); + ret = dio_complete(dio, offset, ret, false); kfree(dio); } else BUG_ON(ret != -EIOCBQUEUED); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 42272d67955a..0afc8c1d8cf3 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3775,7 +3775,8 @@ static ext4_io_end_t *ext4_init_io_end (struct inode *inode, gfp_t flags) } static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, - ssize_t size, void *private) + ssize_t size, void *private, int ret, + bool is_async) { ext4_io_end_t *io_end = iocb->private; struct workqueue_struct *wq; @@ -3784,7 +3785,7 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, /* if not async direct IO or dio with 0 bytes write, just return */ if (!io_end || !size) - return; + goto out; ext_debug("ext4_end_io_dio(): io_end 0x%p" "for inode %lu, iocb 0x%p, offset %llu, size %llu\n", @@ -3795,7 +3796,7 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, if (io_end->flag != EXT4_IO_UNWRITTEN){ ext4_free_io_end(io_end); iocb->private = NULL; - return; + goto out; } io_end->offset = offset; @@ -3812,6 +3813,9 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, list_add_tail(&io_end->list, &ei->i_completed_io_list); spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); iocb->private = NULL; +out: + if (is_async) + aio_complete(iocb, ret, 0); } static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 356e976772bf..96337a4fbbdf 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -578,7 +578,9 @@ bail: static void ocfs2_dio_end_io(struct kiocb *iocb, loff_t offset, ssize_t bytes, - void *private) + void *private, + int ret, + bool is_async) { struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; int level; @@ -592,6 +594,9 @@ static void ocfs2_dio_end_io(struct kiocb *iocb, if (!level) up_read(&inode->i_alloc_sem); ocfs2_rw_unlock(inode, level); + + if (is_async) + aio_complete(iocb, ret, 0); } /* diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 34640d6dbdcb..5895aaf62ace 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -1599,7 +1599,9 @@ xfs_end_io_direct( struct kiocb *iocb, loff_t offset, ssize_t size, - void *private) + void *private, + int ret, + bool is_async) { xfs_ioend_t *ioend = iocb->private; @@ -1645,6 +1647,9 @@ xfs_end_io_direct( * against double-freeing. */ iocb->private = NULL; + + if (is_async) + aio_complete(iocb, ret, 0); } STATIC ssize_t diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h index 4cfc6ea87df8..9f566d92ae3a 100644 --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/linux-2.6/xfs_aops.h @@ -37,6 +37,8 @@ typedef struct xfs_ioend { size_t io_size; /* size of the extent */ xfs_off_t io_offset; /* offset in the file */ struct work_struct io_work; /* xfsdatad work queue */ + struct kiocb *io_iocb; + int io_result; } xfs_ioend_t; extern const struct address_space_operations xfs_address_space_operations; diff --git a/include/linux/fs.h b/include/linux/fs.h index f0f447aed647..509ca14a42c5 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -416,7 +416,8 @@ struct buffer_head; typedef int (get_block_t)(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create); typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, - ssize_t bytes, void *private); + ssize_t bytes, void *private, int ret, + bool is_async); /* * Attribute flags. These should be or-ed together to figure out what -- cgit v1.2.3 From f2b23f0ffc7acdc8a49ba749e3843c43e97c301a Mon Sep 17 00:00:00 2001 From: Jiaying Zhang Date: Tue, 27 Jul 2010 11:56:06 -0400 Subject: ext4: move aio completion after unwritten extent conversion commit 5b3ff237bef43b9e7fb7d1eb858e29b73fd664f9 upstream. This patch is to be applied upon Christoph's "direct-io: move aio_complete into ->end_io" patch. It adds iocb and result fields to struct ext4_io_end_t, so that we can call aio_complete from ext4_end_io_nolock() after the extent conversion has finished. I have verified with Christoph's aio-dio test that used to fail after a few runs on an original kernel but now succeeds on the patched kernel. See http://thread.gmane.org/gmane.comp.file-systems.ext4/19659 for details. Signed-off-by: Jiaying Zhang Signed-off-by: "Theodore Ts'o" Cc: Chuck Ebbert Signed-off-by: Greg Kroah-Hartman --- fs/ext4/ext4.h | 4 +++- fs/ext4/inode.c | 17 ++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 19a4de57128a..4c9f05dc7041 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -167,13 +167,15 @@ struct mpage_da_data { }; #define EXT4_IO_UNWRITTEN 0x1 typedef struct ext4_io_end { - struct list_head list; /* per-file finished AIO list */ + struct list_head list; /* per-file finished IO list */ struct inode *inode; /* file being written to */ unsigned int flag; /* unwritten or not */ struct page *page; /* page struct for buffer write */ loff_t offset; /* offset in the file */ ssize_t size; /* size of the extent */ struct work_struct work; /* data work queue */ + struct kiocb *iocb; /* iocb struct for AIO */ + int result; /* error value for AIO */ } ext4_io_end_t; /* diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 0afc8c1d8cf3..3fb64b9e47c4 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3668,6 +3668,8 @@ static int ext4_end_io_nolock(ext4_io_end_t *io) return ret; } + if (io->iocb) + aio_complete(io->iocb, io->result, 0); /* clear the DIO AIO unwritten flag */ io->flag = 0; return ret; @@ -3767,6 +3769,8 @@ static ext4_io_end_t *ext4_init_io_end (struct inode *inode, gfp_t flags) io->offset = 0; io->size = 0; io->page = NULL; + io->iocb = NULL; + io->result = 0; INIT_WORK(&io->work, ext4_end_io_work); INIT_LIST_HEAD(&io->list); } @@ -3796,12 +3800,18 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, if (io_end->flag != EXT4_IO_UNWRITTEN){ ext4_free_io_end(io_end); iocb->private = NULL; - goto out; +out: + if (is_async) + aio_complete(iocb, ret, 0); + return; } io_end->offset = offset; io_end->size = size; - io_end->flag = EXT4_IO_UNWRITTEN; + if (is_async) { + io_end->iocb = iocb; + io_end->result = ret; + } wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq; /* queue the work to convert unwritten extents to written */ @@ -3813,9 +3823,6 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, list_add_tail(&io_end->list, &ei->i_completed_io_list); spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); iocb->private = NULL; -out: - if (is_async) - aio_complete(iocb, ret, 0); } static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) -- cgit v1.2.3 From 96d55caad409caedd5c0d8342cc76c5d8d6a80fd Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 18 Jul 2010 21:17:10 +0000 Subject: xfs: move aio completion after unwritten extent conversion commit fb511f2150174b18b28ad54708c1adda0df39b17 upstream. If we write into an unwritten extent using AIO we need to complete the AIO request after the extent conversion has finished. Without that a read could race to see see the extent still unwritten and return zeros. For synchronous I/O we already take care of that by flushing the xfsconvertd workqueue (which might be a bit of overkill). To do that add iocb and result fields to struct xfs_ioend, so that we can call aio_complete from xfs_end_io after the extent conversion has happened. Note that we need a new result field as io_error is used for positive errno values, while the AIO code can return negative error values and positive transfer sizes. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Alex Elder Cc: Chuck Ebbert Signed-off-by: Greg Kroah-Hartman --- fs/xfs/linux-2.6/xfs_aops.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 5895aaf62ace..f9f5567bf896 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -275,8 +275,11 @@ xfs_end_io( xfs_finish_ioend(ioend, 0); /* ensure we don't spin on blocked ioends */ delay(1); - } else + } else { + if (ioend->io_iocb) + aio_complete(ioend->io_iocb, ioend->io_result, 0); xfs_destroy_ioend(ioend); + } } /* @@ -309,6 +312,8 @@ xfs_alloc_ioend( atomic_inc(&XFS_I(ioend->io_inode)->i_iocount); ioend->io_offset = 0; ioend->io_size = 0; + ioend->io_iocb = NULL; + ioend->io_result = 0; INIT_WORK(&ioend->io_work, xfs_end_io); return ioend; @@ -1604,6 +1609,7 @@ xfs_end_io_direct( bool is_async) { xfs_ioend_t *ioend = iocb->private; + bool complete_aio = is_async; /* * Non-NULL private data means we need to issue a transaction to @@ -1629,7 +1635,14 @@ xfs_end_io_direct( if (ioend->io_type == IO_READ) { xfs_finish_ioend(ioend, 0); } else if (private && size > 0) { - xfs_finish_ioend(ioend, is_sync_kiocb(iocb)); + if (is_async) { + ioend->io_iocb = iocb; + ioend->io_result = ret; + complete_aio = false; + xfs_finish_ioend(ioend, 0); + } else { + xfs_finish_ioend(ioend, 1); + } } else { /* * A direct I/O write ioend starts it's life in unwritten @@ -1648,7 +1661,7 @@ xfs_end_io_direct( */ iocb->private = NULL; - if (is_async) + if (complete_aio) aio_complete(iocb, ret, 0); } -- cgit v1.2.3 From e3086e9d419b26bd00da78c204c0ab30f1cbbd51 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 9 Aug 2010 13:48:08 +1000 Subject: Revert "Input: appletouch - fix integer overflow issue" commit 6e49c1a407c8af8d779a24fd2428857991514a7b upstream. This reverts commit 04b4b88cca0ebe3813b4b6f014fb6a0db380b137. While the original problem only caused a slight disturbance on the edge of the touchpad, the commit above to "fix" it completely breaks operation on some other models such as mine. We'll sort this out separately, revert the patch for now. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/mouse/appletouch.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 05edd75abca0..a9cf76831634 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -205,8 +205,8 @@ struct atp { bool overflow_warned; int x_old; /* last reported x/y, */ int y_old; /* used for smoothing */ - u8 xy_cur[ATP_XSENSORS + ATP_YSENSORS]; - u8 xy_old[ATP_XSENSORS + ATP_YSENSORS]; + signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS]; + signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; int idlecount; /* number of empty packets */ struct work_struct work; @@ -531,7 +531,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { /* accumulate the change */ - int change = dev->xy_old[i] - dev->xy_cur[i]; + signed char change = dev->xy_old[i] - dev->xy_cur[i]; dev->xy_acc[i] -= change; /* prevent down drifting */ -- cgit v1.2.3 From 96f44a8631764ad755ed701efd7e2b5193e54474 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 30 Jul 2010 10:51:10 +0200 Subject: ALSA: hda - Handle missing NID 0x1b on ALC259 codec commit 5d4abf93ea3192cc666430225a29a4978c97c57d upstream. Since ALC259/269 use the same parser of ALC268, the pin 0x1b was ignored as an invalid widget. Just add this NID to handle properly. This will add the missing mixer controls for some devices. Signed-off-by: Takashi Iwai Cc: David Henningsson Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1a7dfdae3c49..ffe4c32948db 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -13026,6 +13026,7 @@ static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid, dac = 0x02; break; case 0x15: + case 0x1b: case 0x21: /* ALC269vb has this pin, too */ dac = 0x03; break; -- cgit v1.2.3 From 34096073e8ca66f69a42b2697bf1ccc8dc805843 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 30 Jul 2010 14:08:25 +0200 Subject: ALSA: hda - Handle pin NID 0x1a on ALC259/269 commit b08b1637ce1c0196970348bcabf40f04b6b3d58e upstream. The pin NID 0x1a should be handled as well as NID 0x1b. Also added comments. Signed-off-by: Takashi Iwai Cc: David Henningsson Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ffe4c32948db..2b9c88990a7b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -13026,7 +13026,8 @@ static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid, dac = 0x02; break; case 0x15: - case 0x1b: + case 0x1a: /* ALC259/269 only */ + case 0x1b: /* ALC259/269 only */ case 0x21: /* ALC269vb has this pin, too */ dac = 0x03; break; -- cgit v1.2.3 From 738931dd84518fc0ef51bfb4715c11738dbd715e Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 29 Aug 2010 02:13:11 +0100 Subject: Staging: rt2870sta: Add more device IDs from vendor drivers commit 9e693e4375689cb1cd1529aba011de0044f74ef5 upstream. Taken from DPO_RT3070_LinuxSTA_V2.3.0.4_20100604.tar.bz2 and 2010_0709_RT2870_Linux_STA_v2.4.0.1.tar.bz2, with duplicates removed. Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rt2860/usb_main_dev.c | 41 +++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c index c48e85d36f4d..12523921950a 100644 --- a/drivers/staging/rt2860/usb_main_dev.c +++ b/drivers/staging/rt2860/usb_main_dev.c @@ -44,6 +44,7 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x07B8, 0x2870)}, /* AboCom */ {USB_DEVICE(0x07B8, 0x2770)}, /* AboCom */ {USB_DEVICE(0x0DF6, 0x0039)}, /* Sitecom 2770 */ + {USB_DEVICE(0x0DF6, 0x003F)}, /* Sitecom 2770 */ {USB_DEVICE(0x083A, 0x7512)}, /* Arcadyan 2770 */ {USB_DEVICE(0x0789, 0x0162)}, /* Logitec 2870 */ {USB_DEVICE(0x0789, 0x0163)}, /* Logitec 2870 */ @@ -95,7 +96,8 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x050d, 0x815c)}, {USB_DEVICE(0x1482, 0x3C09)}, /* Abocom */ {USB_DEVICE(0x14B2, 0x3C09)}, /* Alpha */ - {USB_DEVICE(0x04E8, 0x2018)}, /* samsung */ + {USB_DEVICE(0x04E8, 0x2018)}, /* samsung linkstick2 */ + {USB_DEVICE(0x1690, 0x0740)}, /* Askey */ {USB_DEVICE(0x5A57, 0x0280)}, /* Zinwell */ {USB_DEVICE(0x5A57, 0x0282)}, /* Zinwell */ {USB_DEVICE(0x7392, 0x7718)}, @@ -105,21 +107,34 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x1737, 0x0071)}, /* Linksys WUSB600N */ {USB_DEVICE(0x0411, 0x00e8)}, /* Buffalo WLI-UC-G300N */ {USB_DEVICE(0x050d, 0x815c)}, /* Belkin F5D8053 */ + {USB_DEVICE(0x100D, 0x9031)}, /* Motorola 2770 */ #endif /* RT2870 // */ #ifdef RT3070 {USB_DEVICE(0x148F, 0x3070)}, /* Ralink 3070 */ {USB_DEVICE(0x148F, 0x3071)}, /* Ralink 3071 */ {USB_DEVICE(0x148F, 0x3072)}, /* Ralink 3072 */ {USB_DEVICE(0x0DB0, 0x3820)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DB0, 0x871C)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DB0, 0x822C)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DB0, 0x871B)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DB0, 0x822B)}, /* Ralink 3070 */ {USB_DEVICE(0x0DF6, 0x003E)}, /* Sitecom 3070 */ {USB_DEVICE(0x0DF6, 0x0042)}, /* Sitecom 3072 */ + {USB_DEVICE(0x0DF6, 0x0048)}, /* Sitecom 3070 */ + {USB_DEVICE(0x0DF6, 0x0047)}, /* Sitecom 3071 */ {USB_DEVICE(0x14B2, 0x3C12)}, /* AL 3070 */ {USB_DEVICE(0x18C5, 0x0012)}, /* Corega 3070 */ {USB_DEVICE(0x083A, 0x7511)}, /* Arcadyan 3070 */ + {USB_DEVICE(0x083A, 0xA701)}, /* SMC 3070 */ + {USB_DEVICE(0x083A, 0xA702)}, /* SMC 3072 */ {USB_DEVICE(0x1740, 0x9703)}, /* EnGenius 3070 */ {USB_DEVICE(0x1740, 0x9705)}, /* EnGenius 3071 */ {USB_DEVICE(0x1740, 0x9706)}, /* EnGenius 3072 */ + {USB_DEVICE(0x1740, 0x9707)}, /* EnGenius 3070 */ + {USB_DEVICE(0x1740, 0x9708)}, /* EnGenius 3071 */ + {USB_DEVICE(0x1740, 0x9709)}, /* EnGenius 3072 */ {USB_DEVICE(0x13D3, 0x3273)}, /* AzureWave 3070 */ + {USB_DEVICE(0x13D3, 0x3305)}, /* AzureWave 3070*/ {USB_DEVICE(0x1044, 0x800D)}, /* Gigabyte GN-WB32L 3070 */ {USB_DEVICE(0x2019, 0xAB25)}, /* Planex Communications, Inc. RT3070 */ {USB_DEVICE(0x07B8, 0x3070)}, /* AboCom 3070 */ @@ -132,14 +147,36 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x07D1, 0x3C0D)}, /* D-Link 3070 */ {USB_DEVICE(0x07D1, 0x3C0E)}, /* D-Link 3070 */ {USB_DEVICE(0x07D1, 0x3C0F)}, /* D-Link 3070 */ + {USB_DEVICE(0x07D1, 0x3C16)}, /* D-Link 3070 */ + {USB_DEVICE(0x07D1, 0x3C17)}, /* D-Link 8070 */ {USB_DEVICE(0x1D4D, 0x000C)}, /* Pegatron Corporation 3070 */ {USB_DEVICE(0x1D4D, 0x000E)}, /* Pegatron Corporation 3070 */ {USB_DEVICE(0x5A57, 0x5257)}, /* Zinwell 3070 */ {USB_DEVICE(0x5A57, 0x0283)}, /* Zinwell 3072 */ {USB_DEVICE(0x04BB, 0x0945)}, /* I-O DATA 3072 */ + {USB_DEVICE(0x04BB, 0x0947)}, /* I-O DATA 3070 */ + {USB_DEVICE(0x04BB, 0x0948)}, /* I-O DATA 3072 */ {USB_DEVICE(0x203D, 0x1480)}, /* Encore 3070 */ + {USB_DEVICE(0x20B8, 0x8888)}, /* PARA INDUSTRIAL 3070 */ + {USB_DEVICE(0x0B05, 0x1784)}, /* Asus 3072 */ + {USB_DEVICE(0x203D, 0x14A9)}, /* Encore 3070*/ + {USB_DEVICE(0x0DB0, 0x899A)}, /* MSI 3070*/ + {USB_DEVICE(0x0DB0, 0x3870)}, /* MSI 3070*/ + {USB_DEVICE(0x0DB0, 0x870A)}, /* MSI 3070*/ + {USB_DEVICE(0x0DB0, 0x6899)}, /* MSI 3070 */ + {USB_DEVICE(0x0DB0, 0x3822)}, /* MSI 3070 */ + {USB_DEVICE(0x0DB0, 0x3871)}, /* MSI 3070 */ + {USB_DEVICE(0x0DB0, 0x871A)}, /* MSI 3070 */ + {USB_DEVICE(0x0DB0, 0x822A)}, /* MSI 3070 */ + {USB_DEVICE(0x0DB0, 0x3821)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DB0, 0x821A)}, /* Ralink 3070 */ + {USB_DEVICE(0x083A, 0xA703)}, /* IO-MAGIC */ + {USB_DEVICE(0x13D3, 0x3307)}, /* Azurewave */ + {USB_DEVICE(0x13D3, 0x3321)}, /* Azurewave */ + {USB_DEVICE(0x07FA, 0x7712)}, /* Edimax */ + {USB_DEVICE(0x0789, 0x0166)}, /* Edimax */ + {USB_DEVICE(0x148F, 0x2070)}, /* Edimax */ #endif /* RT3070 // */ - {USB_DEVICE(0x0DF6, 0x003F)}, /* Sitecom WL-608 */ {USB_DEVICE(0x1737, 0x0077)}, /* Linksys WUSB54GC-EU v3 */ {USB_DEVICE(0x2001, 0x3C09)}, /* D-Link */ {USB_DEVICE(0x2001, 0x3C0A)}, /* D-Link 3072 */ -- cgit v1.2.3 From 920438158deaee30a18bdb3d2f491443c45afdb8 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Tue, 3 Aug 2010 19:15:31 +0000 Subject: staging: hv: Fix missing functions for net_device_ops commit b681b5886bb5d1f5b6750a0ed7c62846da7ccea4 upstream. Fix missing functions for net_device_ops. It's a bug when porting the drivers from 2.6.27 to 2.6.32. In 2.6.27, the default functions for Ethernet, like eth_change_mtu(), were assigned by ether_setup(). But in 2.6.32, these function pointers moved to net_device_ops structure and no longer be assigned in ether_setup(). So we need to set these functions in our driver code. It will ensure the MTU won't be set beyond 1500. Otherwise, this can cause an error on the server side, because the HyperV linux driver doesn't support jumbo frame yet. Signed-off-by: Haiyang Zhang Signed-off-by: Hank Janssen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/netvsc_drv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 55b993298ff4..69cc8f763a0d 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -348,6 +348,9 @@ static const struct net_device_ops device_ops = { .ndo_stop = netvsc_close, .ndo_start_xmit = netvsc_start_xmit, .ndo_set_multicast_list = netvsc_set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, }; static int netvsc_probe(struct device *device) -- cgit v1.2.3 From 0dfc7206252e2dcb48d4b0d69147616261dda491 Mon Sep 17 00:00:00 2001 From: Hank Janssen Date: Thu, 5 Aug 2010 19:29:44 +0000 Subject: staging: hv: Fixed bounce kmap problem by using correct index commit 0c47a70a9a8a6d1ec37a53d2f9cb82f8b8ef8aa2 upstream. Fixed bounce offset kmap problem by using correct index. The symptom of the problem is that in some NAS appliances this problem represents Itself by a unresponsive VM under a load with many clients writing small files. Signed-off-by:Hank Janssen Signed-off-by:Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index d22e35f598ba..062519a09b7d 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -526,7 +526,7 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl, /* ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE); */ - if (j == 0) + if (bounce_addr == 0) bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0); while (srclen) { @@ -587,7 +587,7 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, destlen = orig_sgl[i].length; /* ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE); */ - if (j == 0) + if (bounce_addr == 0) bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0); while (destlen) { -- cgit v1.2.3 From 7d98d6ffab9bca18d610ec08cbd2b41b2911f315 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Thu, 5 Aug 2010 19:30:01 +0000 Subject: staging: hv: Fixed the value of the 64bit-hole inside ring buffer commit e5fa721d1c2a54261a37eb59686e18dee34b6af6 upstream. Fixed the value of the 64bit-hole inside ring buffer, this caused a problem on Hyper-V when running checked Windows builds. Checked builds of Windows are used internally and given to external system integrators at times. They are builds that for example that all elements in a structure follow the definition of that Structure. The bug this fixed was for a field that we did not fill in at all (Because we do Not use it on the Linux side), and the checked build of windows gives errors on it internally to the Windows logs. This fixes that error. Signed-off-by: Hank Janssen Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/ring_buffer.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/hv/ring_buffer.c b/drivers/staging/hv/ring_buffer.c index ae2a10e24d92..c5a38703bd0e 100644 --- a/drivers/staging/hv/ring_buffer.c +++ b/drivers/staging/hv/ring_buffer.c @@ -192,8 +192,7 @@ Description: static inline u64 GetRingBufferIndices(RING_BUFFER_INFO *RingInfo) { - return ((u64)RingInfo->RingBuffer->WriteIndex << 32) - || RingInfo->RingBuffer->ReadIndex; + return (u64)RingInfo->RingBuffer->WriteIndex << 32; } -- cgit v1.2.3 From bac51cb88cbcddeffc45e16a3224b992dc19ec66 Mon Sep 17 00:00:00 2001 From: Hank Janssen Date: Thu, 5 Aug 2010 19:30:31 +0000 Subject: staging: hv: Increased storvsc ringbuffer and max_io_requests commit 15dd1c9f53b31cdc84b8072a88c23fa09527c596 upstream. Increased storvsc ringbuffer and max_io_requests. This now more closely mimics the numbers on Hyper-V. And will allow more IO requests to take place for the SCSI driver. Max_IO is set to double from what it was before, Hyper-V allows it and we have had appliance builder requests to see if it was a problem to increase the number. Ringbuffer size for storvsc is now increased because I have seen A few buffer problems on extremely busy systems. They were Set pretty low before. And since max_io_requests is increased I Really needed to increase the buffer as well. Signed-off-by: Hank Janssen Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_api.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/hv/storvsc_api.h b/drivers/staging/hv/storvsc_api.h index 0063bde9a4b2..8505a1c5f9ee 100644 --- a/drivers/staging/hv/storvsc_api.h +++ b/drivers/staging/hv/storvsc_api.h @@ -28,10 +28,10 @@ #include "vmbus_api.h" /* Defines */ -#define STORVSC_RING_BUFFER_SIZE (10*PAGE_SIZE) +#define STORVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) #define BLKVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) -#define STORVSC_MAX_IO_REQUESTS 64 +#define STORVSC_MAX_IO_REQUESTS 128 /* * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In -- cgit v1.2.3 From eddbe634c915e5243906558cd091a00988b86b00 Mon Sep 17 00:00:00 2001 From: Hank Janssen Date: Wed, 1 Sep 2010 11:10:41 -0700 Subject: staging: hv: Fixed lockup problem with bounce_buffer scatter list commit 77c5ceaff31645ea049c6706b99e699eae81fb88 upstream. Fixed lockup problem with bounce_buffer scatter list which caused crashes in heavy loads. And minor code indentation cleanup in effected area. Removed whitespace and noted minor indentation changes in description as pointed out by Joe Perches. (Thanks for reviewing Joe) Signed-off-by: Hank Janssen Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 062519a09b7d..c1ba458ca79a 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -646,6 +646,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, unsigned int request_size = 0; int i; struct scatterlist *sgl; + unsigned int sg_count = 0; DPRINT_ENTER(STORVSC_DRV); @@ -730,6 +731,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, request->DataBuffer.Length = scsi_bufflen(scmnd); if (scsi_sg_count(scmnd)) { sgl = (struct scatterlist *)scsi_sglist(scmnd); + sg_count = scsi_sg_count(scmnd); /* check if we need to bounce the sgl */ if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) { @@ -764,15 +766,16 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, scsi_sg_count(scmnd)); sgl = cmd_request->bounce_sgl; + sg_count = cmd_request->bounce_sgl_count; } request->DataBuffer.Offset = sgl[0].offset; - for (i = 0; i < scsi_sg_count(scmnd); i++) { + for (i = 0; i < sg_count; i++) { DPRINT_DBG(STORVSC_DRV, "sgl[%d] len %d offset %d\n", i, sgl[i].length, sgl[i].offset); request->DataBuffer.PfnArray[i] = - page_to_pfn(sg_page((&sgl[i]))); + page_to_pfn(sg_page((&sgl[i]))); } } else if (scsi_sglist(scmnd)) { /* ASSERT(scsi_bufflen(scmnd) <= PAGE_SIZE); */ -- cgit v1.2.3 From b7a83862f3f9b3b95719a5c3dafacdf2bb52ddda Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 7 Sep 2010 13:42:41 +0200 Subject: fuse: flush background queue on connection close commit 595afaf9e6ee1b48e13ec4b8bcc8c7dee888161a upstream. David Bartly reported that fuse can hang in fuse_get_req_nofail() when the connection to the filesystem server is no longer active. If bg_queue is not empty then flush_bg_queue() called from request_end() can put more requests on to the pending queue. If this happens while ending requests on the processing queue then those background requests will be queued to the pending list and never ended. Another problem is that fuse_dev_release() didn't wake up processes sleeping on blocked_waitq. Solve this by: a) flushing the background queue before calling end_requests() on the pending and processing queues b) setting blocked = 0 and waking up processes waiting on blocked_waitq() Thanks to David for an excellent bug report. Reported-by: David Bartley Signed-off-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman --- fs/fuse/dev.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 9424796d6634..e5cdabf4945e 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1552,6 +1552,14 @@ __acquires(&fc->lock) } } +static void end_queued_requests(struct fuse_conn *fc) +{ + fc->max_background = UINT_MAX; + flush_bg_queue(fc); + end_requests(fc, &fc->pending); + end_requests(fc, &fc->processing); +} + /* * Abort all requests. * @@ -1578,8 +1586,7 @@ void fuse_abort_conn(struct fuse_conn *fc) fc->connected = 0; fc->blocked = 0; end_io_requests(fc); - end_requests(fc, &fc->pending); - end_requests(fc, &fc->processing); + end_queued_requests(fc); wake_up_all(&fc->waitq); wake_up_all(&fc->blocked_waitq); kill_fasync(&fc->fasync, SIGIO, POLL_IN); @@ -1594,8 +1601,9 @@ int fuse_dev_release(struct inode *inode, struct file *file) if (fc) { spin_lock(&fc->lock); fc->connected = 0; - end_requests(fc, &fc->pending); - end_requests(fc, &fc->processing); + fc->blocked = 0; + end_queued_requests(fc); + wake_up_all(&fc->blocked_waitq); spin_unlock(&fc->lock); fuse_conn_put(fc); } -- cgit v1.2.3 From 58b29725e5bd74da734c6f3fd1eac934a8fed73e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 25 Aug 2010 14:47:38 +0200 Subject: mac80211: delete work timer commit 071249b1d501b1f31a6b1af3fbcbe03158a84e5c upstream. The new workqueue changes helped me find this bug that's been lingering since the changes to the work processing in mac80211 -- the work timer is never deleted properly. Do that to avoid having it fire after all data structures have been freed. It can't be re-armed because all it will do, if running, is schedule the work, but that gets flushed later and won't have anything to do since all work items are gone by now (by way of interface removal). Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 22a384dfab65..52f15fe6f0ed 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -659,6 +659,12 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) rtnl_unlock(); + /* + * Now all work items will be gone, but the + * timer might still be armed, so delete it + */ + del_timer_sync(&local->work_timer); + cancel_work_sync(&local->reconfig_filter); ieee80211_clear_tx_pending(local); -- cgit v1.2.3 From f8d958a95ec0f26ff05bdc75f24887203e701826 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Thu, 12 Aug 2010 14:23:28 +0530 Subject: ath9k_htc: Fix disconnect issue in HT40 mode. commit 71ba186c123630ddab17667ec9ecf7e2ef211295 upstream. Some APs advertise that they may be HT40 capable in the capabilites but the current operating channel configuration may be only HT20. This causes disconnection as ath9k_htc sets WLAN_RC_40_FLAG despite the AP operating in HT20 mode. Hence set this flag only if the current channel configuration is HT40 enabled. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 9d371c18eb41..5f3c47d186d0 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -370,7 +370,8 @@ static int ath9k_htc_init_rate(struct ath9k_htc_priv *priv, priv->tgt_rate.rates.ht_rates.rs_nrates = j; caps = WLAN_RC_HT_FLAG; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) + if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && + (conf_is_ht40(&priv->hw->conf))) caps |= WLAN_RC_40_FLAG; if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) caps |= WLAN_RC_SGI_FLAG; -- cgit v1.2.3 From 5db688f45431d16ac961b441d4125f7b1243051d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 30 Aug 2010 19:26:32 -0400 Subject: ath9k_hw: Fix EEPROM uncompress block reading on AR9003 commit 803288e61e346ba367373bc7d5eeb6e11c81a33c upstream. The EEPROM is compressed on AR9003, upon decompression the wrong upper limit was being used for the block which prevented the 5 GHz CTL indexes from being used, which are stored towards the end of the EEPROM block. This fix allows the actual intended regulatory limits to be used on AR9003 hardware. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index cb4e7daf87f1..5543465a32da 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -768,7 +768,7 @@ static bool ar9300_uncompress_block(struct ath_hw *ah, length = block[it+1]; length &= 0xff; - if (length > 0 && spot >= 0 && spot+length < mdataSize) { + if (length > 0 && spot >= 0 && spot+length <= mdataSize) { ath_print(common, ATH_DBG_EEPROM, "Restore at %d: spot=%d " "offset=%d length=%d\n", -- cgit v1.2.3 From 5f555d8ad4b3e1cd500f6dac90b317c61695a19a Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 30 Aug 2010 19:26:33 -0400 Subject: ath9k_hw: fix parsing of HT40 5 GHz CTLs commit 904879748d7439a6dabdc6be9aad983e216b027d upstream. The 5 GHz CTL indexes were not being read for all hardware devices due to the masking out through the CTL_MODE_M mask being one bit too short. Without this the calibrated regulatory maximum values were not being picked up when devices operate on 5 GHz in HT40 mode. The final output power used for Atheros devices is the minimum between the calibrated CTL values and what CRDA provides. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/eeprom.h | 2 +- drivers/net/wireless/ath/regd.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 5f01a0f40c44..0e8489d17689 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -62,7 +62,7 @@ #define SD_NO_CTL 0xE0 #define NO_CTL 0xff -#define CTL_MODE_M 7 +#define CTL_MODE_M 0xf #define CTL_11A 0 #define CTL_11B 1 #define CTL_11G 2 diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index a1c39526161a..345dd9721b41 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h @@ -31,7 +31,6 @@ enum ctl_group { #define NO_CTL 0xff #define SD_NO_CTL 0xE0 #define NO_CTL 0xff -#define CTL_MODE_M 7 #define CTL_11A 0 #define CTL_11B 1 #define CTL_11G 2 -- cgit v1.2.3 From 1e34225fcdadc793e910d5edfd9c2a48930d42d4 Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Thu, 12 Aug 2010 16:24:26 -0700 Subject: ocfs2: Fix incorrect checksum validation error commit f5ce5a08a40f2086435858ddc80cb40394b082eb upstream. For local mounts, ocfs2_read_locked_inode() calls ocfs2_read_blocks_sync() to read the inode off the disk. The latter first checks to see if that block is cached in the journal, and, if so, returns that block. That is ok. But ocfs2_read_locked_inode() goes wrong when it tries to validate the checksum of such blocks. Blocks that are cached in the journal may not have had their checksum computed as yet. We should not validate the checksums of such blocks. Fixes ossbz#1282 http://oss.oracle.com/bugzilla/show_bug.cgi?id=1282 Signed-off-by: Sunil Mushran Singed-off-by: Tao Ma Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/inode.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index abb0a95cc717..201e7bcec75e 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -488,7 +488,11 @@ static int ocfs2_read_locked_inode(struct inode *inode, OCFS2_BH_IGNORE_CACHE); } else { status = ocfs2_read_blocks_sync(osb, args->fi_blkno, 1, &bh); - if (!status) + /* + * If buffer is in jbd, then its checksum may not have been + * computed as yet. + */ + if (!status && !buffer_jbd(bh)) status = ocfs2_validate_inode_block(osb->sb, bh); } if (status < 0) { -- cgit v1.2.3 From ab36a5f7408546676c79ce7bd20633a5a76ecb58 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Sat, 28 Aug 2010 16:32:55 -0400 Subject: serial: bfin_sport_uart: restore transmit frame sync fix commit 336746918299f2ca16b31490655b4ff7c8824c87 upstream. The large cleanup/rewrite of resources in commit ccf68e59e93181df9353c0cc accidentally reverted an earlier fix in commit a19e8b205915b2925aca75b. So restore it here. Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger Signed-off-by: Greg Kroah-Hartman --- drivers/serial/bfin_sport_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c index e57fb3d228e2..5318dd3774ae 100644 --- a/drivers/serial/bfin_sport_uart.c +++ b/drivers/serial/bfin_sport_uart.c @@ -121,7 +121,7 @@ static int sport_uart_setup(struct sport_uart_port *up, int size, int baud_rate) unsigned int sclk = get_sclk(); /* Set TCR1 and TCR2, TFSR is not enabled for uart */ - SPORT_PUT_TCR1(up, (ITFS | TLSBIT | ITCLK)); + SPORT_PUT_TCR1(up, (LATFS | ITFS | TFSR | TLSBIT | ITCLK)); SPORT_PUT_TCR2(up, size + 1); pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up)); -- cgit v1.2.3 From 654931d5fa6ad8aec46c6220d800235f2085eef6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 14 Aug 2010 11:06:19 +0200 Subject: USB: ehci-ppc-of: problems in unwind commit 08a3b3b1c2e622e378d9086aee9e2e42ce37591d upstream. The iounmap(ehci->ohci_hcctrl_reg); should be the first thing we do because the ioremap() was the last thing we did. Also if we hit any of the goto statements in the original code then it would have led to a NULL dereference of "ehci". This bug was introduced in: 796bcae7361c "USB: powerpc: Workaround for the PPC440EPX USBH_23 errata [take 3]" I modified the few lines in front a little so that my code didn't obscure the return success code path. Signed-off-by: Dan Carpenter Reviewed-by: Grant Likely Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-ppc-of.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index 5aec92866ab3..a07cfd6d593b 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -192,17 +192,19 @@ ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) } rv = usb_add_hcd(hcd, irq, 0); - if (rv == 0) - return 0; + if (rv) + goto err_ehci; + + return 0; +err_ehci: + if (ehci->has_amcc_usb23) + iounmap(ehci->ohci_hcctrl_reg); iounmap(hcd->regs); err_ioremap: irq_dispose_mapping(irq); err_irq: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - - if (ehci->has_amcc_usb23) - iounmap(ehci->ohci_hcctrl_reg); err_rmr: usb_put_hcd(hcd); -- cgit v1.2.3 From f813a03cb84b98820bd2f54273a373f0f01973df Mon Sep 17 00:00:00 2001 From: Maxim Osipov Date: Sat, 21 Aug 2010 14:54:06 +0400 Subject: USB: Fix kernel oops with g_ether and Windows commit 037d3656adbd7e8cb848f01cf5dec423ed76bbe7 upstream. Please find attached patch for https://bugzilla.kernel.org/show_bug.cgi?id=16023 problem. Signed-off-by: Maxim Osipov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/rndis.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 5c0d06c79a81..1043da1fcb16 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -292,9 +292,13 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_VENDOR_DESCRIPTION: pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__); - length = strlen (rndis_per_dev_params [configNr].vendorDescr); - memcpy (outbuf, - rndis_per_dev_params [configNr].vendorDescr, length); + if ( rndis_per_dev_params [configNr].vendorDescr ) { + length = strlen (rndis_per_dev_params [configNr].vendorDescr); + memcpy (outbuf, + rndis_per_dev_params [configNr].vendorDescr, length); + } else { + outbuf[0] = 0; + } retval = 0; break; -- cgit v1.2.3 From 55772a66572b8e888ab6cffc00aa30c4b60aa073 Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Mon, 23 Aug 2010 20:50:57 +0100 Subject: USB: CP210x Add new device ID commit 541e05ec3add5ab5bcf238d60161b53480280b20 upstream. New device ID added for Balluff RFID reader. Signed-off-by: Craig Shelley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 80bf8333bb03..103f9d227fa1 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -109,6 +109,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ { USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */ { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ + { USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */ @@ -122,14 +123,14 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1555, 0x0004) }, /* Owen AC4 USB-RS485 Converter */ { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */ { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ - { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ - { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ - { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ - { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */ { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ { USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */ { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ + { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ + { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ + { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ + { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ { } /* Terminating Entry */ }; -- cgit v1.2.3 From a1af0d0dd0d3258f673c509b20c9834e78dbbfac Mon Sep 17 00:00:00 2001 From: Jason Detring Date: Thu, 26 Aug 2010 15:08:54 -0500 Subject: USB: cp210x: Add B&G H3000 link cable ID commit 0bf7a81c5d447c21db434be35363c44c0a30f598 upstream. This is the cable between an H3000 navigation unit and a multi-function display. http://www.bandg.com/en/Products/H3000/Spares-and-Accessories/Cables/H3000-CPU-USB-Cable-Pack/ Signed-off-by: Jason Detring Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 103f9d227fa1..8ed6ff6e861d 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -88,6 +88,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8149) }, /* West Mountain Radio Computerized Battery Analyzer */ { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ + { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ { USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */ { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ -- cgit v1.2.3 From 91ffbb4a336762e363ef74197e712010c6c31e6f Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Sat, 28 Aug 2010 03:06:29 -0300 Subject: usb: allow drivers to use allocated bandwidth until unbound commit 0791971ba8fbc44e4f476079f856335ed45e6324 upstream. When using the remove sysfs file, the device configuration is set to -1 (unconfigured). This eventually unbind drivers with the bandwidth_mutex held. Some drivers may call functions that hold said mutex, like usb_reset_device. This is the case for rtl8187, for example. This will lead to the same process holding the mutex twice, which deadlocks. Besides, according to Alan Stern: "The deadlock problem probably could be handled somehow, but there's a separate issue: Until the usb_disable_device call finishes unbinding the drivers, the drivers are free to continue using their allocated bandwidth. We musn't change the bandwidth allocations until after the unbinding is done. So this patch is indeed necessary." Unbinding the driver before holding the bandwidth_mutex solves the problem. If any operation after that fails, drivers are not bound again. But that would be a problem anyway that the user may solve resetting the device configuration to one that works, just like he would need to do in most other failure cases. Signed-off-by: Thadeu Lima de Souza Cascardo Cc: Alan Stern Cc: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index fd4c36ea5e46..844683e50383 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1724,6 +1724,15 @@ free_interfaces: if (ret) goto free_interfaces; + /* if it's already configured, clear out old state first. + * getting rid of old interfaces means unbinding their drivers. + */ + if (dev->state != USB_STATE_ADDRESS) + usb_disable_device(dev, 1); /* Skip ep0 */ + + /* Get rid of pending async Set-Config requests for this device */ + cancel_async_set_config(dev); + /* Make sure we have bandwidth (and available HCD resources) for this * configuration. Remove endpoints from the schedule if we're dropping * this configuration to set configuration 0. After this point, the @@ -1733,20 +1742,11 @@ free_interfaces: mutex_lock(&hcd->bandwidth_mutex); ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL); if (ret < 0) { - usb_autosuspend_device(dev); mutex_unlock(&hcd->bandwidth_mutex); + usb_autosuspend_device(dev); goto free_interfaces; } - /* if it's already configured, clear out old state first. - * getting rid of old interfaces means unbinding their drivers. - */ - if (dev->state != USB_STATE_ADDRESS) - usb_disable_device(dev, 1); /* Skip ep0 */ - - /* Get rid of pending async Set-Config requests for this device */ - cancel_async_set_config(dev); - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, configuration, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -1761,8 +1761,8 @@ free_interfaces: if (!cp) { usb_set_device_state(dev, USB_STATE_ADDRESS); usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); - usb_autosuspend_device(dev); mutex_unlock(&hcd->bandwidth_mutex); + usb_autosuspend_device(dev); goto free_interfaces; } mutex_unlock(&hcd->bandwidth_mutex); -- cgit v1.2.3 From 6b0ad10a69b5ecb7e39c249d4e33412e07aa72d7 Mon Sep 17 00:00:00 2001 From: Luke Lowrey Date: Thu, 2 Sep 2010 11:39:49 +0100 Subject: USB: ftdi_sio: Added custom PIDs for ChamSys products commit 657373883417b2618023fd4135d251ba06a2c30a upstream. Added the 0xDAF8 to 0xDAFF PID range for ChamSys limited USB interface/wing products Signed-off-by: Luke Lowrey Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 8 ++++++++ drivers/usb/serial/ftdi_sio_ids.h | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 63ddb2f65cee..0edf4b3741b4 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -753,6 +753,14 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) }, { USB_DEVICE(IONICS_VID, IONICS_PLUGCOMPUTER_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_24_MASTER_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_PC_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_USB_DMX_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MIDI_TIMECODE_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MINI_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MAXI_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MEDIA_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_WING_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 2e95857c9633..15a4583775ad 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -134,6 +134,18 @@ #define FTDI_NDI_FUTURE_3_PID 0xDA73 /* NDI future device #3 */ #define FTDI_NDI_AURORA_SCU_PID 0xDA74 /* NDI Aurora SCU */ +/* + * ChamSys Limited (www.chamsys.co.uk) USB wing/interface product IDs + */ +#define FTDI_CHAMSYS_24_MASTER_WING_PID 0xDAF8 +#define FTDI_CHAMSYS_PC_WING_PID 0xDAF9 +#define FTDI_CHAMSYS_USB_DMX_PID 0xDAFA +#define FTDI_CHAMSYS_MIDI_TIMECODE_PID 0xDAFB +#define FTDI_CHAMSYS_MINI_WING_PID 0xDAFC +#define FTDI_CHAMSYS_MAXI_WING_PID 0xDAFD +#define FTDI_CHAMSYS_MEDIA_WING_PID 0xDAFE +#define FTDI_CHAMSYS_WING_PID 0xDAFF + /* * Westrex International devices submitted by Cory Lee */ -- cgit v1.2.3 From 0679cf82538fcd56cc9f1ac0d892e9e2bf52eb35 Mon Sep 17 00:00:00 2001 From: Dave Ludlow Date: Tue, 31 Aug 2010 14:26:17 -0400 Subject: usb: serial: mos7840: Add USB ID to support the B&B Electronics USOPTL4-2P. commit caf3a636a9f809fdca5fa746e6687096457accb1 upstream. Add the USB ID needed to support B&B Electronic's 2-port, optically-isolated, powered, USB to RS485 converter. Signed-off-by: Dave Ludlow Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 585b7e663740..9a5ea9dba464 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -129,6 +129,7 @@ #define BANDB_DEVICE_ID_USOPTL4_2 0xAC42 #define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 #define BANDB_DEVICE_ID_USOPTL2_4 0xAC24 +#define BANDB_DEVICE_ID_USOPTL4_2P 0xBC02 /* This driver also supports * ATEN UC2324 device using Moschip MCS7840 @@ -192,6 +193,7 @@ static const struct usb_device_id moschip_port_id_table[] = { {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4P)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, {} /* terminating entry */ @@ -209,6 +211,7 @@ static const struct usb_device_id moschip_id_table_combined[] __devinitconst = { {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4P)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, {} /* terminating entry */ -- cgit v1.2.3 From d2d1443783dd810cc7d6987a2510ecf43f549f62 Mon Sep 17 00:00:00 2001 From: Dave Ludlow Date: Wed, 1 Sep 2010 12:33:30 -0400 Subject: usb: serial: mos7840: Add USB IDs to support more B&B USB/RS485 converters. commit 870408c8291015872a7a0b583673a9e56b3e73f4 upstream. Add the USB IDs needed to support the B&B USOPTL4-4P, USO9ML2-2P, and USO9ML2-4P. This patch expands and corrects a typo in the patch sent on 08-31-2010. Signed-off-by: Dave Ludlow Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 9a5ea9dba464..1c9b6e9b2386 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -119,17 +119,20 @@ * by making a change here, in moschip_port_id_table, and in * moschip_id_table_combined */ -#define USB_VENDOR_ID_BANDB 0x0856 -#define BANDB_DEVICE_ID_USO9ML2_2 0xAC22 -#define BANDB_DEVICE_ID_USO9ML2_4 0xAC24 -#define BANDB_DEVICE_ID_US9ML2_2 0xAC29 -#define BANDB_DEVICE_ID_US9ML2_4 0xAC30 -#define BANDB_DEVICE_ID_USPTL4_2 0xAC31 -#define BANDB_DEVICE_ID_USPTL4_4 0xAC32 -#define BANDB_DEVICE_ID_USOPTL4_2 0xAC42 -#define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 -#define BANDB_DEVICE_ID_USOPTL2_4 0xAC24 -#define BANDB_DEVICE_ID_USOPTL4_2P 0xBC02 +#define USB_VENDOR_ID_BANDB 0x0856 +#define BANDB_DEVICE_ID_USO9ML2_2 0xAC22 +#define BANDB_DEVICE_ID_USO9ML2_2P 0xBC00 +#define BANDB_DEVICE_ID_USO9ML2_4 0xAC24 +#define BANDB_DEVICE_ID_USO9ML2_4P 0xBC01 +#define BANDB_DEVICE_ID_US9ML2_2 0xAC29 +#define BANDB_DEVICE_ID_US9ML2_4 0xAC30 +#define BANDB_DEVICE_ID_USPTL4_2 0xAC31 +#define BANDB_DEVICE_ID_USPTL4_4 0xAC32 +#define BANDB_DEVICE_ID_USOPTL4_2 0xAC42 +#define BANDB_DEVICE_ID_USOPTL4_2P 0xBC02 +#define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 +#define BANDB_DEVICE_ID_USOPTL4_4P 0xBC03 +#define BANDB_DEVICE_ID_USOPTL2_4 0xAC24 /* This driver also supports * ATEN UC2324 device using Moschip MCS7840 @@ -185,15 +188,18 @@ static const struct usb_device_id moschip_port_id_table[] = { {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)}, - {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4P)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, {} /* terminating entry */ @@ -203,15 +209,18 @@ static const struct usb_device_id moschip_id_table_combined[] __devinitconst = { {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)}, - {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4P)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, {} /* terminating entry */ -- cgit v1.2.3 From 652d6da0a0a42632330737e1d6d87c82da819fcf Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Tue, 31 Aug 2010 09:38:51 -0400 Subject: ima: always maintain counters commit e950598d43dce8d97e7d5270808393425d1e5cbd upstream. commit 8262bb85da allocated the inode integrity struct (iint) before any inodes were created. Only after IMA was initialized in late_initcall were the counters updated. This patch updates the counters, whether or not IMA has been initialized, to resolve 'imbalance' messages. This patch fixes the bug as reported in bugzilla: 15673. When the i915 is builtin, the ring_buffer is initialized before IMA, causing the imbalance message on suspend. Reported-by: Thomas Meyer Signed-off-by: Mimi Zohar Tested-by: Thomas Meyer Tested-by: David Safford Signed-off-by: James Morris Signed-off-by: Greg Kroah-Hartman --- security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_iint.c | 4 +++- security/integrity/ima/ima_main.c | 8 +++++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 16d100d3fc38..3fbcd1dda0ef 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -35,6 +35,7 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; #define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS) /* set during initialization */ +extern int iint_initialized; extern int ima_initialized; extern int ima_used_chip; extern char *ima_hash; diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c index 7625b85c2274..afba4aef812f 100644 --- a/security/integrity/ima/ima_iint.c +++ b/security/integrity/ima/ima_iint.c @@ -22,9 +22,10 @@ RADIX_TREE(ima_iint_store, GFP_ATOMIC); DEFINE_SPINLOCK(ima_iint_lock); - static struct kmem_cache *iint_cache __read_mostly; +int iint_initialized = 0; + /* ima_iint_find_get - return the iint associated with an inode * * ima_iint_find_get gets a reference to the iint. Caller must @@ -141,6 +142,7 @@ static int __init ima_iintcache_init(void) iint_cache = kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, SLAB_PANIC, init_once); + iint_initialized = 1; return 0; } security_initcall(ima_iintcache_init); diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index f93641382e9f..e662b89d4079 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -148,12 +148,14 @@ void ima_counts_get(struct file *file) struct ima_iint_cache *iint; int rc; - if (!ima_initialized || !S_ISREG(inode->i_mode)) + if (!iint_initialized || !S_ISREG(inode->i_mode)) return; iint = ima_iint_find_get(inode); if (!iint) return; mutex_lock(&iint->mutex); + if (!ima_initialized) + goto out; rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK); if (rc < 0) goto out; @@ -213,7 +215,7 @@ void ima_file_free(struct file *file) struct inode *inode = file->f_dentry->d_inode; struct ima_iint_cache *iint; - if (!ima_initialized || !S_ISREG(inode->i_mode)) + if (!iint_initialized || !S_ISREG(inode->i_mode)) return; iint = ima_iint_find_get(inode); if (!iint) @@ -230,7 +232,7 @@ static int process_measurement(struct file *file, const unsigned char *filename, { struct inode *inode = file->f_dentry->d_inode; struct ima_iint_cache *iint; - int rc; + int rc = 0; if (!ima_initialized || !S_ISREG(inode->i_mode)) return 0; -- cgit v1.2.3 From aef30a0bfdf6c10565285fff1ae8400b34ee0d81 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Wed, 1 Sep 2010 18:37:12 +0100 Subject: USB: cxacru: Use a bulk/int URB to access the command endpoint commit 902ffc3c707c1d459ea57428a619a807cbe412f9 upstream. The command endpoint is either a bulk or interrupt endpoint, but using the wrong type of transfer causes an error if CONFIG_USB_DEBUG is enabled after commit f661c6f8c67bd55e93348f160d590ff9edf08904, which checks for this mismatch. Detect which type of endpoint it is and use a bulk/int URB as appropriate. There are other function calls specifying a bulk pipe, but usb_clear_halt doesn't use the pipe type (only the endpoint) and usb_bulk_msg auto-detects interrupt transfers. Signed-off-by: Simon Arlott Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/cxacru.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index c89990f5e018..b24025d9dd23 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -1128,6 +1128,7 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, { struct cxacru_data *instance; struct usb_device *usb_dev = interface_to_usbdev(intf); + struct usb_host_endpoint *cmd_ep = usb_dev->ep_in[CXACRU_EP_CMD]; int ret; /* instance init */ @@ -1172,15 +1173,34 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, goto fail; } - usb_fill_int_urb(instance->rcv_urb, + if (!cmd_ep) { + dbg("cxacru_bind: no command endpoint"); + ret = -ENODEV; + goto fail; + } + + if ((cmd_ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_INT) { + usb_fill_int_urb(instance->rcv_urb, usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD), instance->rcv_buf, PAGE_SIZE, cxacru_blocking_completion, &instance->rcv_done, 1); - usb_fill_int_urb(instance->snd_urb, + usb_fill_int_urb(instance->snd_urb, usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD), instance->snd_buf, PAGE_SIZE, cxacru_blocking_completion, &instance->snd_done, 4); + } else { + usb_fill_bulk_urb(instance->rcv_urb, + usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_CMD), + instance->rcv_buf, PAGE_SIZE, + cxacru_blocking_completion, &instance->rcv_done); + + usb_fill_bulk_urb(instance->snd_urb, + usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD), + instance->snd_buf, PAGE_SIZE, + cxacru_blocking_completion, &instance->snd_done); + } mutex_init(&instance->cm_serialize); -- cgit v1.2.3 From 7b4275fe849cd3f0fd9843e6bdfdd51dfc804d39 Mon Sep 17 00:00:00 2001 From: Toby Gray Date: Wed, 1 Sep 2010 16:01:19 +0100 Subject: USB: cdc-acm: Adding second ACM channel support for various Nokia and one Samsung phones commit 4035e45632c2a8bb4edae83c20447051bd9a9604 upstream. S60 phones from Nokia and Samsung expose two ACM channels. The first is a modem with a standard AT-command interface, which is picked up correctly by CDC-ACM. The second ACM port is marked as having a vendor-specific protocol. This means that the ACM driver will not claim the second channel by default. This adds support for the second ACM channel for the following devices: Nokia E63 Nokia E75 Nokia 6760 Slide Nokia E52 Nokia E55 Nokia E72 Nokia X6 Nokia N97 Mini Nokia 5800 Xpressmusic Nokia E90 Samsung GTi8510 (INNOV8) Signed-off-by: Toby Gray Cc: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 162c95a088ed..fdf45023cf4d 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1487,6 +1487,11 @@ static int acm_reset_resume(struct usb_interface *intf) USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \ USB_CDC_ACM_PROTO_VENDOR) +#define SAMSUNG_PCSUITE_ACM_INFO(x) \ + USB_DEVICE_AND_INTERFACE_INFO(0x04e7, x, \ + USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \ + USB_CDC_ACM_PROTO_VENDOR) + /* * USB driver structure. */ @@ -1597,6 +1602,17 @@ static const struct usb_device_id acm_ids[] = { { NOKIA_PCSUITE_ACM_INFO(0x0108), }, /* Nokia 5320 XpressMusic 2G */ { NOKIA_PCSUITE_ACM_INFO(0x01f5), }, /* Nokia N97, RM-505 */ { NOKIA_PCSUITE_ACM_INFO(0x02e3), }, /* Nokia 5230, RM-588 */ + { NOKIA_PCSUITE_ACM_INFO(0x0178), }, /* Nokia E63 */ + { NOKIA_PCSUITE_ACM_INFO(0x010e), }, /* Nokia E75 */ + { NOKIA_PCSUITE_ACM_INFO(0x02d9), }, /* Nokia 6760 Slide */ + { NOKIA_PCSUITE_ACM_INFO(0x01d0), }, /* Nokia E52 */ + { NOKIA_PCSUITE_ACM_INFO(0x0223), }, /* Nokia E72 */ + { NOKIA_PCSUITE_ACM_INFO(0x0275), }, /* Nokia X6 */ + { NOKIA_PCSUITE_ACM_INFO(0x026c), }, /* Nokia N97 Mini */ + { NOKIA_PCSUITE_ACM_INFO(0x0154), }, /* Nokia 5800 XpressMusic */ + { NOKIA_PCSUITE_ACM_INFO(0x04ce), }, /* Nokia E90 */ + { NOKIA_PCSUITE_ACM_INFO(0x01d4), }, /* Nokia E55 */ + { SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */ /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ -- cgit v1.2.3 From 67584f5e2e19499c8484991684110730080d7221 Mon Sep 17 00:00:00 2001 From: Philippe Corbes Date: Tue, 31 Aug 2010 19:31:32 +0200 Subject: USB: cdc-acm: Add pseudo modem without AT command capabilities commit 5b239f0aebd4dd6f85b13decf5e18e86e35d57f0 upstream. cdc-acm.c : Manage pseudo-modem without AT commands capabilities Enable to drive electronic simple gadgets based on microcontrolers. The Interface descriptor is like this: bInterfaceClass 2 Communications bInterfaceSubClass 2 Abstract (modem) bInterfaceProtocol 0 None Signed-off-by: Philippe Corbes Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index fdf45023cf4d..764b9b3a903f 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1621,6 +1621,10 @@ static const struct usb_device_id acm_ids[] = { .driver_info = NOT_A_MODEM, }, + /* control interfaces without any protocol set */ + { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, + USB_CDC_PROTO_NONE) }, + /* control interfaces with various AT-command sets */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_ACM_PROTO_AT_V25TER) }, -- cgit v1.2.3 From f723b548653996b6e7dfbabd8e431e3fd1dc3c17 Mon Sep 17 00:00:00 2001 From: Toby Gray Date: Thu, 2 Sep 2010 10:46:20 +0100 Subject: USB: cdc-acm: Fixing crash when ACM probing interfaces with no endpoint descriptors. commit 577045c0a76e34294f902a7d5d60e90b04d094d0 upstream. Certain USB devices, such as the Nokia X6 mobile phone, don't expose any endpoint descriptors on some of their interfaces. If the ACM driver is forced to probe all interfaces on a device the a NULL pointer dereference will occur when the ACM driver attempts to use the endpoint of the alternative settings. One way to get the ACM driver to probe all the interfaces is by using the /sys/bus/usb/drivers/cdc_acm/new_id interface. This patch checks that the endpoint pointer for the current alternate settings is non-NULL before using it. Signed-off-by: Toby Gray Cc: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 764b9b3a903f..a1aacb048eb3 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -971,7 +971,8 @@ static int acm_probe(struct usb_interface *intf, } if (!buflen) { - if (intf->cur_altsetting->endpoint->extralen && + if (intf->cur_altsetting->endpoint && + intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) { dev_dbg(&intf->dev, "Seeking extra descriptors on endpoint\n"); -- cgit v1.2.3 From a6a72ec7a8343e9839f689513f6cc7b35b57487b Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Thu, 2 Sep 2010 08:35:47 +0200 Subject: ALSA: hda - Add a new hp-laptop model for Conexant 5066, tested on HP G60 commit 048e78a5bc22c27410cb5ca9680c3c7ac400607f upstream. This new model adds the following functionality to HP G60: - Automute of internal speakers - Autoswitch of internal/external mics - Remove SPDIF not physically present BugLink: http://launchpad.net/bugs/587388 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 + sound/pci/hda/patch_conexant.c | 57 ++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 1d38b0dfba95..dc25bb84b83b 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -288,6 +288,7 @@ Conexant 5051 Conexant 5066 ============= laptop Basic Laptop config (default) + hp-laptop HP laptops, e g G60 dell-laptop Dell laptops olpc-xo-1_5 OLPC XO 1.5 ideapad Lenovo IdeaPad U150 diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index baadda40f1d0..5c75e7686fab 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -116,6 +116,7 @@ struct conexant_spec { unsigned int dell_vostro:1; unsigned int ideapad:1; unsigned int thinkpad:1; + unsigned int hp_laptop:1; unsigned int ext_mic_present; unsigned int recording; @@ -2219,6 +2220,18 @@ static void cxt5066_ideapad_automic(struct hda_codec *codec) } } +/* toggle input of built-in digital mic and mic jack appropriately */ +static void cxt5066_hp_laptop_automic(struct hda_codec *codec) +{ + unsigned int present; + + present = snd_hda_jack_detect(codec, 0x1b); + snd_printdd("CXT5066: external microphone present=%d\n", present); + snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, + present ? 1 : 3); +} + + /* toggle input of built-in digital mic and mic jack appropriately order is: external mic -> dock mic -> interal mic */ static void cxt5066_thinkpad_automic(struct hda_codec *codec) @@ -2327,6 +2340,20 @@ static void cxt5066_ideapad_event(struct hda_codec *codec, unsigned int res) } } +/* unsolicited event for jack sensing */ +static void cxt5066_hp_laptop_event(struct hda_codec *codec, unsigned int res) +{ + snd_printdd("CXT5066_hp_laptop: unsol event %x (%x)\n", res, res >> 26); + switch (res >> 26) { + case CONEXANT_HP_EVENT: + cxt5066_hp_automute(codec); + break; + case CONEXANT_MIC_EVENT: + cxt5066_hp_laptop_automic(codec); + break; + } +} + /* unsolicited event for jack sensing */ static void cxt5066_thinkpad_event(struct hda_codec *codec, unsigned int res) { @@ -2910,6 +2937,14 @@ static struct hda_verb cxt5066_init_verbs_portd_lo[] = { { } /* end */ }; + +static struct hda_verb cxt5066_init_verbs_hp_laptop[] = { + {0x14, AC_VERB_SET_CONNECT_SEL, 0x0}, + {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, + {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, + { } /* end */ +}; + /* initialize jack-sensing, too */ static int cxt5066_init(struct hda_codec *codec) { @@ -2925,6 +2960,8 @@ static int cxt5066_init(struct hda_codec *codec) cxt5066_ideapad_automic(codec); else if (spec->thinkpad) cxt5066_thinkpad_automic(codec); + else if (spec->hp_laptop) + cxt5066_hp_laptop_automic(codec); } cxt5066_set_mic_boost(codec); return 0; @@ -2952,6 +2989,7 @@ enum { CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */ CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ + CXT5066_HP_LAPTOP, /* HP Laptop */ CXT5066_MODELS }; @@ -2962,6 +3000,7 @@ static const char *cxt5066_models[CXT5066_MODELS] = { [CXT5066_DELL_VOSTO] = "dell-vostro", [CXT5066_IDEAPAD] = "ideapad", [CXT5066_THINKPAD] = "thinkpad", + [CXT5066_HP_LAPTOP] = "hp-laptop", }; static struct snd_pci_quirk cxt5066_cfg_tbl[] = { @@ -2973,6 +3012,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTO), SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), + SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), @@ -3032,6 +3072,23 @@ static int patch_cxt5066(struct hda_codec *codec) spec->num_init_verbs++; spec->dell_automute = 1; break; + case CXT5066_HP_LAPTOP: + codec->patch_ops.init = cxt5066_init; + codec->patch_ops.unsol_event = cxt5066_hp_laptop_event; + spec->init_verbs[spec->num_init_verbs] = + cxt5066_init_verbs_hp_laptop; + spec->num_init_verbs++; + spec->hp_laptop = 1; + spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; + spec->mixers[spec->num_mixers++] = cxt5066_mixers; + /* no S/PDIF out */ + spec->multiout.dig_out_nid = 0; + /* input source automatically selected */ + spec->input_mux = NULL; + spec->port_d_mode = 0; + spec->mic_boost = 3; /* default 30dB gain */ + break; + case CXT5066_OLPC_XO_1_5: codec->patch_ops.init = cxt5066_olpc_init; codec->patch_ops.unsol_event = cxt5066_olpc_unsol_event; -- cgit v1.2.3 From a8ff79954a0cd5041c2c7ddd96be446ecf1273de Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Fri, 3 Sep 2010 10:53:11 +0200 Subject: ALSA: usb-audio: fix detection of vendor-specific device protocol settings commit a2acad8298a42b7be684a32fafaf83332bba9c2b upstream. The Audio Class v2 support code in 2.6.35 added checks for the bInterfaceProtocol field. However, there are devices (usually those detected by vendor-specific quirks) that do not have one of the predefined values in this field, which made the driver reject them. To fix this regression, restore the old behaviour, i.e., assume that a device with an unknown bInterfaceProtocol field (other than UAC_VERSION_2) has more or less UAC-v1-compatible descriptors. [compile warning fixes by tiwai] Signed-off-by: Clemens Ladisch Cc: Daniel Mack Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/card.c | 9 +++++---- sound/usb/clock.c | 3 +-- sound/usb/endpoint.c | 11 ++++++----- sound/usb/format.c | 14 ++++++++++---- sound/usb/mixer.c | 10 +++++++++- sound/usb/pcm.c | 3 +-- 6 files changed, 32 insertions(+), 18 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index 7a8ac1d81be7..745bd782faab 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -216,6 +216,11 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) } switch (protocol) { + default: + snd_printdd(KERN_WARNING "unknown interface protocol %#02x, assuming v1\n", + protocol); + /* fall through */ + case UAC_VERSION_1: { struct uac_ac_header_descriptor_v1 *h1 = control_header; @@ -253,10 +258,6 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) break; } - - default: - snd_printk(KERN_ERR "unknown protocol version 0x%02x\n", protocol); - return -EINVAL; } return 0; diff --git a/sound/usb/clock.c b/sound/usb/clock.c index b5855114667e..aeda4c77839c 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -304,12 +304,11 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, switch (altsd->bInterfaceProtocol) { case UAC_VERSION_1: + default: return set_sample_rate_v1(chip, iface, alts, fmt, rate); case UAC_VERSION_2: return set_sample_rate_v2(chip, iface, alts, fmt, rate); } - - return -EINVAL; } diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 6f6596cf2b19..0aac62800012 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -274,6 +274,12 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) /* get audio formats */ switch (protocol) { + default: + snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n", + dev->devnum, iface_no, altno, protocol); + protocol = UAC_VERSION_1; + /* fall through */ + case UAC_VERSION_1: { struct uac_as_header_descriptor_v1 *as = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); @@ -335,11 +341,6 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) dev->devnum, iface_no, altno, as->bTerminalLink); continue; } - - default: - snd_printk(KERN_ERR "%d:%u:%d : unknown interface protocol %04x\n", - dev->devnum, iface_no, altno, protocol); - continue; } /* get format type */ diff --git a/sound/usb/format.c b/sound/usb/format.c index 30364aba79cc..440d7c3cb009 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -49,7 +49,8 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, u64 pcm_formats; switch (protocol) { - case UAC_VERSION_1: { + case UAC_VERSION_1: + default: { struct uac_format_type_i_discrete_descriptor *fmt = _fmt; sample_width = fmt->bBitResolution; sample_bytes = fmt->bSubframeSize; @@ -64,9 +65,6 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, format <<= 1; break; } - - default: - return -EINVAL; } pcm_formats = 0; @@ -385,6 +383,10 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, * audio class v2 uses class specific EP0 range requests for that. */ switch (protocol) { + default: + snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n", + chip->dev->devnum, fp->iface, fp->altsetting, protocol); + /* fall through */ case UAC_VERSION_1: fp->channels = fmt->bNrChannels; ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7); @@ -435,6 +437,10 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, fp->channels = 1; switch (protocol) { + default: + snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n", + chip->dev->devnum, fp->iface, fp->altsetting, protocol); + /* fall through */ case UAC_VERSION_1: { struct uac_format_type_ii_discrete_descriptor *fmt = _fmt; brate = le16_to_cpu(fmt->wMaxBitRate); diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 736d134cc03c..2a4377f42dd9 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2168,7 +2168,15 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, } host_iface = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0]; - mixer->protocol = get_iface_desc(host_iface)->bInterfaceProtocol; + switch (get_iface_desc(host_iface)->bInterfaceProtocol) { + case UAC_VERSION_1: + default: + mixer->protocol = UAC_VERSION_1; + break; + case UAC_VERSION_2: + mixer->protocol = UAC_VERSION_2; + break; + } if ((err = snd_usb_mixer_controls(mixer)) < 0 || (err = snd_usb_mixer_status_create(mixer)) < 0) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 456829882f40..b40a24853c1d 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -173,13 +173,12 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, switch (altsd->bInterfaceProtocol) { case UAC_VERSION_1: + default: return init_pitch_v1(chip, iface, alts, fmt); case UAC_VERSION_2: return init_pitch_v2(chip, iface, alts, fmt); } - - return -EINVAL; } /* -- cgit v1.2.3 From 62f520f10a2b563d3d6239925af57c8f865b48b3 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 7 Sep 2010 13:37:10 +0200 Subject: ALSA: virtuoso: work around missing reset in the Xonar DS Windows driver commit 4c25b93223340deff73381cc47f9244fb379a74d upstream. For the WM8776 chip, this driver uses a different sample format and more features than the Windows driver. When rebooting from Linux into Windows, the latter driver does not reset the chip but assumes all its registers have their default settings, so we get garbled sound or, if the output happened to be muted before rebooting, no sound. To make that driver happy, hook our driver's cleanup function into the shutdown notifier and ensure that the chip gets reset. Signed-off-by: Clemens Ladisch Reported-and-tested-by: Nathan Schagen Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/oxygen/oxygen.h | 1 + sound/pci/oxygen/oxygen_lib.c | 21 ++++++++++++++++++--- sound/pci/oxygen/virtuoso.c | 1 + sound/pci/oxygen/xonar_wm87x6.c | 1 + 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index 6147216af744..a3409edcfb50 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h @@ -155,6 +155,7 @@ void oxygen_pci_remove(struct pci_dev *pci); int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); int oxygen_pci_resume(struct pci_dev *pci); #endif +void oxygen_pci_shutdown(struct pci_dev *pci); /* oxygen_mixer.c */ diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index fad03d64e3ad..7e93cf884437 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c @@ -519,16 +519,21 @@ static void oxygen_init(struct oxygen *chip) } } -static void oxygen_card_free(struct snd_card *card) +static void oxygen_shutdown(struct oxygen *chip) { - struct oxygen *chip = card->private_data; - spin_lock_irq(&chip->reg_lock); chip->interrupt_mask = 0; chip->pcm_running = 0; oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); spin_unlock_irq(&chip->reg_lock); +} + +static void oxygen_card_free(struct snd_card *card) +{ + struct oxygen *chip = card->private_data; + + oxygen_shutdown(chip); if (chip->irq >= 0) free_irq(chip->irq, chip); flush_scheduled_work(); @@ -778,3 +783,13 @@ int oxygen_pci_resume(struct pci_dev *pci) } EXPORT_SYMBOL(oxygen_pci_resume); #endif /* CONFIG_PM */ + +void oxygen_pci_shutdown(struct pci_dev *pci) +{ + struct snd_card *card = pci_get_drvdata(pci); + struct oxygen *chip = card->private_data; + + oxygen_shutdown(chip); + chip->model.cleanup(chip); +} +EXPORT_SYMBOL(oxygen_pci_shutdown); diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index f03a2f2cffee..06c863e86e3d 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c @@ -95,6 +95,7 @@ static struct pci_driver xonar_driver = { .suspend = oxygen_pci_suspend, .resume = oxygen_pci_resume, #endif + .shutdown = oxygen_pci_shutdown, }; static int __init alsa_card_xonar_init(void) diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c index dbc4b89d74e4..0b89932fb8c4 100644 --- a/sound/pci/oxygen/xonar_wm87x6.c +++ b/sound/pci/oxygen/xonar_wm87x6.c @@ -193,6 +193,7 @@ static void xonar_ds_init(struct oxygen *chip) static void xonar_ds_cleanup(struct oxygen *chip) { xonar_disable_output(chip); + wm8776_write(chip, WM8776_RESET, 0); } static void xonar_ds_suspend(struct oxygen *chip) -- cgit v1.2.3 From 0aa2a836bdf2314b452a7c08a614d5b55029a93c Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 7 Sep 2010 13:38:49 +0200 Subject: ALSA: virtuoso: fix setting of Xonar DS line-in/mic-in controls commit fe6ce80ae25953d95ebaf9bce27b585218cda25c upstream. The Line and Mic inputs cannot be used at the same time, so the driver has to automatically disable one of them if both are set. However, it forgot to notify userspace about this change, so the mixer state would be inconsistent. To fix this, check if the other control gets muted, and send a notification event in this case. Signed-off-by: Clemens Ladisch Reported-and-tested-by: Nathan Schagen Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/oxygen/xonar_wm87x6.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c index 0b89932fb8c4..b82c1cfa96f5 100644 --- a/sound/pci/oxygen/xonar_wm87x6.c +++ b/sound/pci/oxygen/xonar_wm87x6.c @@ -53,6 +53,8 @@ struct xonar_wm87x6 { struct xonar_generic generic; u16 wm8776_regs[0x17]; u16 wm8766_regs[0x10]; + struct snd_kcontrol *line_adcmux_control; + struct snd_kcontrol *mic_adcmux_control; struct snd_kcontrol *lc_controls[13]; }; @@ -604,6 +606,7 @@ static int wm8776_input_mux_put(struct snd_kcontrol *ctl, { struct oxygen *chip = ctl->private_data; struct xonar_wm87x6 *data = chip->model_data; + struct snd_kcontrol *other_ctl; unsigned int mux_bit = ctl->private_value; u16 reg; int changed; @@ -611,8 +614,18 @@ static int wm8776_input_mux_put(struct snd_kcontrol *ctl, mutex_lock(&chip->mutex); reg = data->wm8776_regs[WM8776_ADCMUX]; if (value->value.integer.value[0]) { - reg &= ~0x003; reg |= mux_bit; + /* line-in and mic-in are exclusive */ + mux_bit ^= 3; + if (reg & mux_bit) { + reg &= ~mux_bit; + if (mux_bit == 1) + other_ctl = data->line_adcmux_control; + else + other_ctl = data->mic_adcmux_control; + snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, + &other_ctl->id); + } } else reg &= ~mux_bit; changed = reg != data->wm8776_regs[WM8776_ADCMUX]; @@ -964,7 +977,13 @@ static int xonar_ds_mixer_init(struct oxygen *chip) err = snd_ctl_add(chip->card, ctl); if (err < 0) return err; + if (!strcmp(ctl->id.name, "Line Capture Switch")) + data->line_adcmux_control = ctl; + else if (!strcmp(ctl->id.name, "Mic Capture Switch")) + data->mic_adcmux_control = ctl; } + if (!data->line_adcmux_control || !data->mic_adcmux_control) + return -ENXIO; BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls)); for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) { ctl = snd_ctl_new1(&lc_controls[i], chip); -- cgit v1.2.3 From 7ab99e2ebb57576e1e853e9de18f242558196f6f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 6 Sep 2010 09:13:45 +0200 Subject: ALSA: seq/oss - Fix double-free at error path of snd_seq_oss_open() commit 27f7ad53829f79e799a253285318bff79ece15bd upstream. The error handling in snd_seq_oss_open() has several bad codes that do dereferecing released pointers and double-free of kmalloc'ed data. The object dp is release in free_devinfo() that is called via private_free callback. The rest shouldn't touch this object any more. The patch changes delete_port() to call kfree() in any case, and gets rid of unnecessary calls of destructors in snd_seq_oss_open(). Fixes CVE-2010-3080. Reported-and-tested-by: Tavis Ormandy Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/core/seq/oss/seq_oss_init.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c index 685712276ac9..69cd7b3c362d 100644 --- a/sound/core/seq/oss/seq_oss_init.c +++ b/sound/core/seq/oss/seq_oss_init.c @@ -281,13 +281,10 @@ snd_seq_oss_open(struct file *file, int level) return 0; _error: - snd_seq_oss_writeq_delete(dp->writeq); - snd_seq_oss_readq_delete(dp->readq); snd_seq_oss_synth_cleanup(dp); snd_seq_oss_midi_cleanup(dp); - delete_port(dp); delete_seq_queue(dp->queue); - kfree(dp); + delete_port(dp); return rc; } @@ -350,8 +347,10 @@ create_port(struct seq_oss_devinfo *dp) static int delete_port(struct seq_oss_devinfo *dp) { - if (dp->port < 0) + if (dp->port < 0) { + kfree(dp); return 0; + } debug_printk(("delete_port %i\n", dp->port)); return snd_seq_event_port_detach(dp->cseq, dp->port); -- cgit v1.2.3 From e45ef8fb8d9e08be9997f2c530ce83237351373f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 Sep 2010 08:27:02 +0200 Subject: ALSA: usb - Release capture substream URBs properly commit 76195fb096ca6db2f8bbaffb96e3025aaf1649a0 upstream. Due to the wrong "return" in the loop, a capture substream won't be released at disconnection properly if the device is capture only and has no playback substream. This caused Oops occasionally at the device reconnection. Reported-by: Kim Minhyoung Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/card.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index 745bd782faab..d1924d716816 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -126,7 +126,7 @@ static void snd_usb_stream_disconnect(struct list_head *head) for (idx = 0; idx < 2; idx++) { subs = &as->substream[idx]; if (!subs->num_formats) - return; + continue; snd_usb_release_substream_urbs(subs, 1); subs->interface = -1; } -- cgit v1.2.3 From 511ff6d61096894acff3664951b52f8584c78776 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 Sep 2010 11:58:30 +0200 Subject: ALSA: hda - Add quirk for Lenovo T400s commit 4d155641c81203440da64c4633b4efaab75f63b3 upstream. Lenovo T400s requires the quirk to make automatic HP/mic switching working. Reported-by: Frank Becker Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_conexant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 5c75e7686fab..4eee494e7e87 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3015,6 +3015,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), + SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD), -- cgit v1.2.3 From e9073fb9554a452a7ec7731b7f36f1e8e07106fe Mon Sep 17 00:00:00 2001 From: Brian Austin Date: Tue, 7 Sep 2010 14:36:22 -0500 Subject: ALSA: hda - Add errata initverb sequence for CS42xx codecs commit a769cbcf60cee51f4431c0938acd39e7e5b76b8d upstream. Add init verb sequence for errata ER880C3 http://www.cirrus.com/en/pubs/errata/ER880C3.pdf Signed-off-by: Brian Austin Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_cirrus.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 350ee8ac4153..059565f10ee9 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -972,6 +972,53 @@ static struct hda_verb cs_coef_init_verbs[] = { {} /* terminator */ }; +/* Errata: CS4207 rev C0/C1/C2 Silicon + * + * http://www.cirrus.com/en/pubs/errata/ER880C3.pdf + * + * 6. At high temperature (TA > +85°C), the digital supply current (IVD) + * may be excessive (up to an additional 200 μA), which is most easily + * observed while the part is being held in reset (RESET# active low). + * + * Root Cause: At initial powerup of the device, the logic that drives + * the clock and write enable to the S/PDIF SRC RAMs is not properly + * initialized. + * Certain random patterns will cause a steady leakage current in those + * RAM cells. The issue will resolve once the SRCs are used (turned on). + * + * Workaround: The following verb sequence briefly turns on the S/PDIF SRC + * blocks, which will alleviate the issue. + */ + +static struct hda_verb cs_errata_init_verbs[] = { + {0x01, AC_VERB_SET_POWER_STATE, 0x00}, /* AFG: D0 */ + {0x11, AC_VERB_SET_PROC_STATE, 0x01}, /* VPW: processing on */ + + {0x11, AC_VERB_SET_COEF_INDEX, 0x0008}, + {0x11, AC_VERB_SET_PROC_COEF, 0x9999}, + {0x11, AC_VERB_SET_COEF_INDEX, 0x0017}, + {0x11, AC_VERB_SET_PROC_COEF, 0xa412}, + {0x11, AC_VERB_SET_COEF_INDEX, 0x0001}, + {0x11, AC_VERB_SET_PROC_COEF, 0x0009}, + + {0x07, AC_VERB_SET_POWER_STATE, 0x00}, /* S/PDIF Rx: D0 */ + {0x08, AC_VERB_SET_POWER_STATE, 0x00}, /* S/PDIF Tx: D0 */ + + {0x11, AC_VERB_SET_COEF_INDEX, 0x0017}, + {0x11, AC_VERB_SET_PROC_COEF, 0x2412}, + {0x11, AC_VERB_SET_COEF_INDEX, 0x0008}, + {0x11, AC_VERB_SET_PROC_COEF, 0x0000}, + {0x11, AC_VERB_SET_COEF_INDEX, 0x0001}, + {0x11, AC_VERB_SET_PROC_COEF, 0x0008}, + {0x11, AC_VERB_SET_PROC_STATE, 0x00}, + + {0x07, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Rx: D3 */ + {0x08, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Tx: D3 */ + /*{0x01, AC_VERB_SET_POWER_STATE, 0x03},*/ /* AFG: D3 This is already handled */ + + {} /* terminator */ +}; + /* SPDIF setup */ static void init_digital(struct hda_codec *codec) { @@ -991,6 +1038,9 @@ static int cs_init(struct hda_codec *codec) { struct cs_spec *spec = codec->spec; + /* init_verb sequence for C0/C1/C2 errata*/ + snd_hda_sequence_write(codec, cs_errata_init_verbs); + snd_hda_sequence_write(codec, cs_coef_init_verbs); if (spec->gpio_mask) { -- cgit v1.2.3 From e46eb17f9d1ed722daae4297623e267c3fc17547 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 Sep 2010 14:57:04 +0200 Subject: ALSA: hda - Fix wrong HP pin detection in snd_hda_parse_pin_def_config() commit 122661b67899980f1372812d907e73ebcfb3d037 upstream. snd_hda_parse_pin_def_config() has some workaround for re-assigning some pins declared as headphones to line-outs. This didn't work properly for some cases because it used memmove() stupidly wrongly. Reference: Novell bnc#637263 https://bugzilla.novell.com/show_bug.cgi?id=637263 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index ba2098d20ccc..00515c767dee 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -4360,7 +4360,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, cfg->hp_outs--; memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1, sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i)); - memmove(sequences_hp + i - 1, sequences_hp + i, + memmove(sequences_hp + i, sequences_hp + i + 1, sizeof(sequences_hp[0]) * (cfg->hp_outs - i)); } } -- cgit v1.2.3 From 7a2a632d33a13111fdc7cb141958db8894653279 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 2 Sep 2010 17:13:15 +0800 Subject: ALSA: usb-audio: Assume first control interface is for audio commit 7b6717e144de6592e614fd7fc3b914b6bf686a9d upstream. For devices with more than one control interface, let's assume the first one contains the audio controls. Unfortunately, there is no field in any of the descriptors to tell us whether a control interface is for audio or MIDI controls, so a better check is not easy to implement. On a composite device with audio and MIDI functions, for example, the code currently overwrites chip->ctrl_intf, causing operations on the control interface to fail if they are issued after the device probe. Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/card.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index d1924d716816..ceeba8918454 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -466,7 +466,13 @@ static void *snd_usb_audio_probe(struct usb_device *dev, goto __error; } - chip->ctrl_intf = alts; + /* + * For devices with more than one control interface, we assume the + * first contains the audio controls. We might need a more specific + * check here in the future. + */ + if (!chip->ctrl_intf) + chip->ctrl_intf = alts; if (err > 0) { /* create normal USB audio interfaces */ -- cgit v1.2.3 From ac6042dd0aa278b74f774fa35af05721e865a13a Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 9 Aug 2010 22:41:40 -0600 Subject: ALSA: hda - patch_nvhdmi.c: Add missing codec IDs, unify names commit 9cf2657d05f9f9e04c3e113d68bf7cef5a942070 upstream. * Add missing codec IDs. * Modify some existing codec names for discrete GPUs to match newly added IDs. Note: existing names were a mixture of marketing and engineering GPU names. Equally, there's no reason that codec IDs have to be specific to a particular GPU or board, so identify codecs in a less marketing-oriented fashion. * Reformat codec ID table so it's easier to read, for me at least. Signed-off-by: Stephen Warren Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_nvhdmi.c | 61 +++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c index b0652acee9b2..88ae0f2cc3b2 100644 --- a/sound/pci/hda/patch_nvhdmi.c +++ b/sound/pci/hda/patch_nvhdmi.c @@ -541,26 +541,32 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) * patch entries */ static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { - { .id = 0x10de0002, .name = "MCP77/78 HDMI", - .patch = patch_nvhdmi_8ch_7x }, - { .id = 0x10de0003, .name = "MCP77/78 HDMI", - .patch = patch_nvhdmi_8ch_7x }, - { .id = 0x10de0005, .name = "MCP77/78 HDMI", - .patch = patch_nvhdmi_8ch_7x }, - { .id = 0x10de0006, .name = "MCP77/78 HDMI", - .patch = patch_nvhdmi_8ch_7x }, - { .id = 0x10de0007, .name = "MCP79/7A HDMI", - .patch = patch_nvhdmi_8ch_7x }, - { .id = 0x10de000a, .name = "GT220 HDMI", - .patch = patch_nvhdmi_8ch_89 }, - { .id = 0x10de000b, .name = "GT21x HDMI", - .patch = patch_nvhdmi_8ch_89 }, - { .id = 0x10de000c, .name = "MCP89 HDMI", - .patch = patch_nvhdmi_8ch_89 }, - { .id = 0x10de000d, .name = "GT240 HDMI", - .patch = patch_nvhdmi_8ch_89 }, - { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, - { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, + { .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, + { .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, + { .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, + { .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, + { .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x }, + { .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, + { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, {} /* terminator */ }; @@ -573,6 +579,21 @@ MODULE_ALIAS("snd-hda-codec-id:10de000a"); MODULE_ALIAS("snd-hda-codec-id:10de000b"); MODULE_ALIAS("snd-hda-codec-id:10de000c"); MODULE_ALIAS("snd-hda-codec-id:10de000d"); +MODULE_ALIAS("snd-hda-codec-id:10de0010"); +MODULE_ALIAS("snd-hda-codec-id:10de0011"); +MODULE_ALIAS("snd-hda-codec-id:10de0012"); +MODULE_ALIAS("snd-hda-codec-id:10de0013"); +MODULE_ALIAS("snd-hda-codec-id:10de0014"); +MODULE_ALIAS("snd-hda-codec-id:10de0018"); +MODULE_ALIAS("snd-hda-codec-id:10de0019"); +MODULE_ALIAS("snd-hda-codec-id:10de001a"); +MODULE_ALIAS("snd-hda-codec-id:10de001b"); +MODULE_ALIAS("snd-hda-codec-id:10de001c"); +MODULE_ALIAS("snd-hda-codec-id:10de0040"); +MODULE_ALIAS("snd-hda-codec-id:10de0041"); +MODULE_ALIAS("snd-hda-codec-id:10de0042"); +MODULE_ALIAS("snd-hda-codec-id:10de0043"); +MODULE_ALIAS("snd-hda-codec-id:10de0044"); MODULE_ALIAS("snd-hda-codec-id:10de0067"); MODULE_ALIAS("snd-hda-codec-id:10de8001"); -- cgit v1.2.3 From b77c254d8d66e5e9aa81239fedba9f3d568097d9 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Thu, 9 Sep 2010 16:38:09 -0700 Subject: swap: prevent reuse during hibernation commit b73d7fcecd93dc15eaa3c45c8c587b613f6673c4 upstream. Move the hibernation check from scan_swap_map() into try_to_free_swap(): to catch not only the common case when hibernation's allocation itself triggers swap reuse, but also the less likely case when concurrent page reclaim (shrink_page_list) might happen to try_to_free_swap from a page. Hibernation already clears __GFP_IO from the gfp_allowed_mask, to stop reclaim from going to swap: check that to prevent swap reuse too. Signed-off-by: Hugh Dickins Cc: KAMEZAWA Hiroyuki Cc: KOSAKI Motohiro Cc: "Rafael J. Wysocki" Cc: Ondrej Zary Cc: Andrea Gelmini Cc: Balbir Singh Cc: Andrea Arcangeli Cc: Nigel Cunningham Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/swapfile.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/mm/swapfile.c b/mm/swapfile.c index f08d165871b3..ed5151079f59 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -318,10 +318,8 @@ checks: if (offset > si->highest_bit) scan_base = offset = si->lowest_bit; - /* reuse swap entry of cache-only swap if not hibernation. */ - if (vm_swap_full() - && usage == SWAP_HAS_CACHE - && si->swap_map[offset] == SWAP_HAS_CACHE) { + /* reuse swap entry of cache-only swap if not busy. */ + if (vm_swap_full() && si->swap_map[offset] == SWAP_HAS_CACHE) { int swap_was_freed; spin_unlock(&swap_lock); swap_was_freed = __try_to_reclaim_swap(si, offset); @@ -688,6 +686,24 @@ int try_to_free_swap(struct page *page) if (page_swapcount(page)) return 0; + /* + * Once hibernation has begun to create its image of memory, + * there's a danger that one of the calls to try_to_free_swap() + * - most probably a call from __try_to_reclaim_swap() while + * hibernation is allocating its own swap pages for the image, + * but conceivably even a call from memory reclaim - will free + * the swap from a page which has already been recorded in the + * image as a clean swapcache page, and then reuse its swap for + * another page of the image. On waking from hibernation, the + * original page might be freed under memory pressure, then + * later read back in from swap, now with the wrong data. + * + * Hibernation clears bits from gfp_allowed_mask to prevent + * memory reclaim from writing to disk, so check that here. + */ + if (!(gfp_allowed_mask & __GFP_IO)) + return 0; + delete_from_swap_cache(page); SetPageDirty(page); return 1; -- cgit v1.2.3 From eb5b5fb7667d74ceeb3c409e20ac0340f48c9d20 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Thu, 9 Sep 2010 16:38:11 -0700 Subject: swap: discard while swapping only if SWAP_FLAG_DISCARD commit 3399446632739fcd05fd8b272b476a69c6e6d14a upstream. Tests with recent firmware on Intel X25-M 80GB and OCZ Vertex 60GB SSDs show a shift since I last tested in December: in part because of firmware updates, in part because of the necessary move from barriers to awaiting completion at the block layer. While discard at swapon still shows as slightly beneficial on both, discarding 1MB swap cluster when allocating is now disadvanteous: adds 25% overhead on Intel, adds 230% on OCZ (YMMV). Surrender: discard as presently implemented is more hindrance than help for swap; but might prove useful on other devices, or with improvements. So continue to do the discard at swapon, but make discard while swapping conditional on a SWAP_FLAG_DISCARD to sys_swapon() (which has been using only the lower 16 bits of int flags). We can add a --discard or -d to swapon(8), and a "discard" to swap in /etc/fstab: matching the mount option for btrfs, ext4, fat, gfs2, nilfs2. Signed-off-by: Hugh Dickins Cc: Christoph Hellwig Cc: Nigel Cunningham Cc: Tejun Heo Cc: Jens Axboe Cc: James Bottomley Cc: "Martin K. Petersen" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/swap.h | 3 ++- mm/swapfile.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index ff4acea9bbdb..11c1e471ab7b 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -19,6 +19,7 @@ struct bio; #define SWAP_FLAG_PREFER 0x8000 /* set if swap priority specified */ #define SWAP_FLAG_PRIO_MASK 0x7fff #define SWAP_FLAG_PRIO_SHIFT 0 +#define SWAP_FLAG_DISCARD 0x10000 /* discard swap cluster after use */ static inline int current_is_kswapd(void) { @@ -142,7 +143,7 @@ struct swap_extent { enum { SWP_USED = (1 << 0), /* is slot in swap_info[] used? */ SWP_WRITEOK = (1 << 1), /* ok to write to this swap? */ - SWP_DISCARDABLE = (1 << 2), /* blkdev supports discard */ + SWP_DISCARDABLE = (1 << 2), /* swapon+blkdev support discard */ SWP_DISCARDING = (1 << 3), /* now discarding a free cluster */ SWP_SOLIDSTATE = (1 << 4), /* blkdev seeks are cheap */ SWP_CONTINUED = (1 << 5), /* swap_map has count continuation */ diff --git a/mm/swapfile.c b/mm/swapfile.c index ed5151079f59..5667db7b36e9 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -2050,7 +2050,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) p->flags |= SWP_SOLIDSTATE; p->cluster_next = 1 + (random32() % p->highest_bit); } - if (discard_swap(p) == 0) + if (discard_swap(p) == 0 && (swap_flags & SWAP_FLAG_DISCARD)) p->flags |= SWP_DISCARDABLE; } -- cgit v1.2.3 From 697c5a83eae7228e8591bbbf0f88dbbb73d281f7 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 9 Sep 2010 16:38:10 -0700 Subject: swap: do not send discards as barriers commit 8f2ae0faa3a119158c4dcfe89926d6fad5f5332c upstream. The swap code already uses synchronous discards, no need to add I/O barriers. This fixes the worst of the terrible slowdown in swap allocation for hibernation, reported on 2.6.35 by Nigel Cunningham; but does not entirely eliminate that regression. [tj@kernel.org: superflous newlines removed] Signed-off-by: Christoph Hellwig Tested-by: Nigel Cunningham Signed-off-by: Tejun Heo Signed-off-by: Hugh Dickins Cc: Jens Axboe Cc: James Bottomley Cc: "Martin K. Petersen" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/swapfile.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/mm/swapfile.c b/mm/swapfile.c index 5667db7b36e9..7c703ff2f36f 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -139,8 +139,7 @@ static int discard_swap(struct swap_info_struct *si) nr_blocks = ((sector_t)se->nr_pages - 1) << (PAGE_SHIFT - 9); if (nr_blocks) { err = blkdev_issue_discard(si->bdev, start_block, - nr_blocks, GFP_KERNEL, - BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER); + nr_blocks, GFP_KERNEL, BLKDEV_IFL_WAIT); if (err) return err; cond_resched(); @@ -151,8 +150,7 @@ static int discard_swap(struct swap_info_struct *si) nr_blocks = (sector_t)se->nr_pages << (PAGE_SHIFT - 9); err = blkdev_issue_discard(si->bdev, start_block, - nr_blocks, GFP_KERNEL, - BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER); + nr_blocks, GFP_KERNEL, BLKDEV_IFL_WAIT); if (err) break; @@ -191,8 +189,7 @@ static void discard_swap_cluster(struct swap_info_struct *si, start_block <<= PAGE_SHIFT - 9; nr_blocks <<= PAGE_SHIFT - 9; if (blkdev_issue_discard(si->bdev, start_block, - nr_blocks, GFP_NOIO, BLKDEV_IFL_WAIT | - BLKDEV_IFL_BARRIER)) + nr_blocks, GFP_NOIO, BLKDEV_IFL_WAIT)) break; } -- cgit v1.2.3 From a319dbda7a69f218b56d7a3424f2dba3b7dc2350 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 25 Aug 2010 09:12:29 +0200 Subject: sysfs: checking for NULL instead of ERR_PTR commit 57f9bdac2510cd7fda58e4a111d250861eb1ebeb upstream. d_path() returns an ERR_PTR and it doesn't return NULL. Signed-off-by: Dan Carpenter Reviewed-by: "Eric W. Biederman" Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 1beaa739d0a6..cd796847c813 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -340,7 +340,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file) char *p; p = d_path(&file->f_path, last_sysfs_file, sizeof(last_sysfs_file)); - if (p) + if (!IS_ERR(p)) memmove(last_sysfs_file, p, strlen(p) + 1); /* need attr_sd for attr and ops, its parent for kobj */ -- cgit v1.2.3 From 3f0cfc091f8593dc2ccb282d8155225fd56b03f1 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Fri, 13 Aug 2010 16:29:04 +0200 Subject: oprofile: fix crash when accessing freed task structs commit 750d857c682f4db60d14722d430c7ccc35070962 upstream. This patch fixes a crash during shutdown reported below. The crash is caused by accessing already freed task structs. The fix changes the order for registering and unregistering notifier callbacks. All notifiers must be initialized before buffers start working. To stop buffer synchronization we cancel all workqueues, unregister the notifier callback and then flush all buffers. After all of this we finally can free all tasks listed. This should avoid accessing freed tasks. On 22.07.10 01:14:40, Benjamin Herrenschmidt wrote: > So the initial observation is a spinlock bad magic followed by a crash > in the spinlock debug code: > > [ 1541.586531] BUG: spinlock bad magic on CPU#5, events/5/136 > [ 1541.597564] Unable to handle kernel paging request for data at address 0x6b6b6b6b6b6b6d03 > > Backtrace looks like: > > spin_bug+0x74/0xd4 > ._raw_spin_lock+0x48/0x184 > ._spin_lock+0x10/0x24 > .get_task_mm+0x28/0x8c > .sync_buffer+0x1b4/0x598 > .wq_sync_buffer+0xa0/0xdc > .worker_thread+0x1d8/0x2a8 > .kthread+0xa8/0xb4 > .kernel_thread+0x54/0x70 > > So we are accessing a freed task struct in the work queue when > processing the samples. Reported-by: Benjamin Herrenschmidt Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman --- drivers/oprofile/buffer_sync.c | 27 ++++++++++++++------------- drivers/oprofile/cpu_buffer.c | 2 -- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index a9352b2c7ac4..b7e755f4178a 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -141,16 +141,6 @@ static struct notifier_block module_load_nb = { .notifier_call = module_load_notify, }; - -static void end_sync(void) -{ - end_cpu_work(); - /* make sure we don't leak task structs */ - process_task_mortuary(); - process_task_mortuary(); -} - - int sync_start(void) { int err; @@ -158,7 +148,7 @@ int sync_start(void) if (!zalloc_cpumask_var(&marked_cpus, GFP_KERNEL)) return -ENOMEM; - start_cpu_work(); + mutex_lock(&buffer_mutex); err = task_handoff_register(&task_free_nb); if (err) @@ -173,7 +163,10 @@ int sync_start(void) if (err) goto out4; + start_cpu_work(); + out: + mutex_unlock(&buffer_mutex); return err; out4: profile_event_unregister(PROFILE_MUNMAP, &munmap_nb); @@ -182,7 +175,6 @@ out3: out2: task_handoff_unregister(&task_free_nb); out1: - end_sync(); free_cpumask_var(marked_cpus); goto out; } @@ -190,11 +182,20 @@ out1: void sync_stop(void) { + /* flush buffers */ + mutex_lock(&buffer_mutex); + end_cpu_work(); unregister_module_notifier(&module_load_nb); profile_event_unregister(PROFILE_MUNMAP, &munmap_nb); profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb); task_handoff_unregister(&task_free_nb); - end_sync(); + mutex_unlock(&buffer_mutex); + flush_scheduled_work(); + + /* make sure we don't leak task structs */ + process_task_mortuary(); + process_task_mortuary(); + free_cpumask_var(marked_cpus); } diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 219f79e2210a..f179ac2ea801 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -120,8 +120,6 @@ void end_cpu_work(void) cancel_delayed_work(&b->work); } - - flush_scheduled_work(); } /* -- cgit v1.2.3 From ad8096c8a02ca8340cdeb34ab0f368c97adffd1f Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 30 Aug 2010 10:56:18 +0200 Subject: oprofile, x86: fix init_sysfs error handling commit 10f0412f57f2a76a90eff4376f59cbb0a39e4e18 upstream. On failure init_sysfs() might not properly free resources. The error code of the function is not checked. And, when reinitializing the exit function might be called twice. This patch fixes all this. Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman --- arch/x86/oprofile/nmi_int.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index f6b48f6c5951..73a41d3c6c09 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -568,8 +568,13 @@ static int __init init_sysfs(void) int error; error = sysdev_class_register(&oprofile_sysclass); - if (!error) - error = sysdev_register(&device_oprofile); + if (error) + return error; + + error = sysdev_register(&device_oprofile); + if (error) + sysdev_class_unregister(&oprofile_sysclass); + return error; } @@ -695,6 +700,8 @@ int __init op_nmi_init(struct oprofile_operations *ops) char *cpu_type = NULL; int ret = 0; + using_nmi = 0; + if (!cpu_has_apic) return -ENODEV; @@ -774,7 +781,10 @@ int __init op_nmi_init(struct oprofile_operations *ops) mux_init(ops); - init_sysfs(); + ret = init_sysfs(); + if (ret) + return ret; + using_nmi = 1; printk(KERN_INFO "oprofile: using NMI interrupt.\n"); return 0; -- cgit v1.2.3 From b68ccacffdfb1fbcab3a39a960260c617569af8b Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 1 Sep 2010 14:50:50 +0200 Subject: oprofile, x86: fix init_sysfs() function stub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 269f45c25028c75fe10e6d9be86e7202ab461fbc upstream. The use of the return value of init_sysfs() with commit 10f0412 oprofile, x86: fix init_sysfs error handling discovered the following build error for !CONFIG_PM: .../linux/arch/x86/oprofile/nmi_int.c: In function ‘op_nmi_init’: .../linux/arch/x86/oprofile/nmi_int.c:784: error: expected expression before ‘do’ make[2]: *** [arch/x86/oprofile/nmi_int.o] Error 1 make[1]: *** [arch/x86/oprofile] Error 2 This patch fixes this. Reported-by: Ingo Molnar Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman --- arch/x86/oprofile/nmi_int.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 73a41d3c6c09..cfe4faabb0f6 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -585,8 +585,10 @@ static void exit_sysfs(void) } #else -#define init_sysfs() do { } while (0) -#define exit_sysfs() do { } while (0) + +static inline int init_sysfs(void) { return 0; } +static inline void exit_sysfs(void) { } + #endif /* CONFIG_PM */ static int __init p4_init(char **cpu_type) -- cgit v1.2.3 From 25de680b83ee668dd4d7c3d530217cb70cf58833 Mon Sep 17 00:00:00 2001 From: Alan Ott Date: Tue, 17 Aug 2010 00:44:04 -0400 Subject: HID: Set Report ID properly for Output reports on the Control endpoint. commit c29771c2d8ceb907ed45eb8c7fc0450308140aca upstream. When I made commit 29129a98e6fc89 ("HID: Send Report ID when numbered reports are sent over the control endpoint"), I didn't account for *buf not being the report ID anymore, as buf is incremented. Signed-off-by: Alan Ott Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/usbhid/hid-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index b729c0286679..ffd6899d4ba0 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -828,6 +828,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co } } else { int skipped_report_id = 0; + int report_id = buf[0]; if (buf[0] == 0x0) { /* Don't send the Report ID */ buf++; @@ -837,7 +838,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), HID_REQ_SET_REPORT, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - ((report_type + 1) << 8) | *buf, + ((report_type + 1) << 8) | report_id, interface->desc.bInterfaceNumber, buf, count, USB_CTRL_SET_TIMEOUT); /* count also the report id, if this was a numbered report. */ -- cgit v1.2.3 From ff4adc0b087a98b7202a53fd134d18fb078c1d12 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 7 Sep 2010 14:05:31 +0200 Subject: libata: skip EH autopsy and recovery during suspend commit e2f3d75fc0e4a0d03c61872bad39ffa2e74a04ff upstream. For some mysterious reason, certain hardware reacts badly to usual EH actions while the system is going for suspend. As the devices won't be needed until the system is resumed, ask EH to skip usual autopsy and recovery and proceed directly to suspend. Signed-off-by: Tejun Heo Tested-by: Stephan Diestelhorst Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-core.c | 14 +++++++++++++- drivers/ata/libata-eh.c | 4 ++++ include/linux/libata.h | 1 + 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index ddf8e4862787..1f24267b6d2b 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5434,6 +5434,7 @@ static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg, */ int ata_host_suspend(struct ata_host *host, pm_message_t mesg) { + unsigned int ehi_flags = ATA_EHI_QUIET; int rc; /* @@ -5442,7 +5443,18 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg) */ ata_lpm_enable(host); - rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1); + /* + * On some hardware, device fails to respond after spun down + * for suspend. As the device won't be used before being + * resumed, we don't need to touch the device. Ask EH to skip + * the usual stuff and proceed directly to suspend. + * + * http://thread.gmane.org/gmane.linux.ide/46764 + */ + if (mesg.event == PM_EVENT_SUSPEND) + ehi_flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_NO_RECOVERY; + + rc = ata_host_request_pm(host, mesg, 0, ehi_flags, 1); if (rc == 0) host->dev->power.power_state = mesg; return rc; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index f77a67303f8b..da5a55bf1566 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -3234,6 +3234,10 @@ static int ata_eh_skip_recovery(struct ata_link *link) if (link->flags & ATA_LFLAG_DISABLED) return 1; + /* skip if explicitly requested */ + if (ehc->i.flags & ATA_EHI_NO_RECOVERY) + return 1; + /* thaw frozen port and recover failed devices */ if ((ap->pflags & ATA_PFLAG_FROZEN) || ata_link_nr_enabled(link)) return 0; diff --git a/include/linux/libata.h b/include/linux/libata.h index b85f3ff34d7d..8a9b4cffbcf1 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -335,6 +335,7 @@ enum { ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */ ATA_EHI_NO_AUTOPSY = (1 << 2), /* no autopsy */ ATA_EHI_QUIET = (1 << 3), /* be quiet */ + ATA_EHI_NO_RECOVERY = (1 << 4), /* no recovery */ ATA_EHI_DID_SOFTRESET = (1 << 16), /* already soft-reset this port */ ATA_EHI_DID_HARDRESET = (1 << 17), /* already soft-reset this port */ -- cgit v1.2.3 From 63b754139e3c4b1e24e0e488a7864b136738032f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 9 Sep 2010 17:13:31 +0200 Subject: libata,pata_via: revert ata_wait_idle() removal from ata_sff/via_tf_load() commit 40c6023031369ae5573e622ca54fa3ffe89fb865 upstream. Commit 978c0666 (libata: Remove excess delay in the tf_load path) removed ata_wait_idle() from ata_sff_tf_load() and via_tf_load(). This caused obscure detection problems in sata_sil. https://bugzilla.kernel.org/show_bug.cgi?id=16606 The commit was pure performance optimization. Revert it for now. Reported-by: Dieter Plaetinck Reported-by: Jan Beulich Bisected-by: gianluca Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-sff.c | 3 +++ drivers/ata/pata_via.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 494eb9f1329f..cde20ffa1116 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -418,6 +418,7 @@ void ata_sff_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) if (ioaddr->ctl_addr) iowrite8(tf->ctl, ioaddr->ctl_addr); ap->last_ctl = tf->ctl; + ata_wait_idle(ap); } if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { @@ -453,6 +454,8 @@ void ata_sff_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) iowrite8(tf->device, ioaddr->device_addr); VPRINTK("device 0x%X\n", tf->device); } + + ata_wait_idle(ap); } EXPORT_SYMBOL_GPL(ata_sff_tf_load); diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index 5e659885de16..ac8d7d97e408 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -417,6 +417,8 @@ static void via_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) tf->lbam, tf->lbah); } + + ata_wait_idle(ap); } static int via_port_start(struct ata_port *ap) -- cgit v1.2.3 From 2b88bc4f87ca83631af8ab3286964a547835a0df Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 27 Aug 2010 11:09:15 +0200 Subject: ahci: fix hang on failed softreset commit f1f5a807b051eddd3f302e503d39214e5bde0ef2 upstream. ahci_do_softreset() compared the current time and deadline in reverse when calculating timeout for SRST issue. The result is that if @deadline is in future, SRST is issued with 0 timeout, which hasn't caused any problem because it later waits for DRDY with the correct timeout. If deadline is already exceeded by the time SRST is about to be issued, the timeout calculation underflows and if the device doesn't respond, timeout doesn't trigger for a _very_ long time. Reverse the incorrect comparison order. Signed-off-by: Tejun Heo Reported-by: Anssi Hannula Tested-by: Gwendal Grignou Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 81e772a94d59..98c80e1ab6e9 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1320,7 +1320,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, /* issue the first D2H Register FIS */ msecs = 0; now = jiffies; - if (time_after(now, deadline)) + if (time_after(deadline, now)) msecs = jiffies_to_msecs(deadline - now); tf.ctl |= ATA_SRST; -- cgit v1.2.3 From 803ac2f1bd3eea08152c253dbc5f7c9865010331 Mon Sep 17 00:00:00 2001 From: Jeff Moyer Date: Thu, 9 Sep 2010 16:37:33 -0700 Subject: O_DIRECT: fix the splitting up of contiguous I/O commit 7a801ac6f5067539ceb5fad0fe90ec49fc156e47 upstream. commit c2c6ca4 (direct-io: do not merge logically non-contiguous requests) introduced a bug whereby all O_DIRECT I/Os were submitted a page at a time to the block layer. The problem is that the code expected dio->block_in_file to correspond to the current page in the dio. In fact, it corresponds to the previous page submitted via submit_page_section. This was purely an oversight, as the dio->cur_page_fs_offset field was introduced for just this purpose. This patch simply uses the correct variable when calculating whether there is a mismatch between contiguous logical blocks and contiguous physical blocks (as described in the comments). I also switched the if conditional following this check to an else if, to ensure that we never call dio_bio_submit twice for the same dio (in theory, this should not happen, anyway). I've tested this by running blktrace and verifying that a 64KB I/O was submitted as a single I/O. I also ran the patched kernel through xfstests' aio tests using xfs, ext4 (with 1k and 4k block sizes) and btrfs and verified that there were no regressions as compared to an unpatched kernel. Signed-off-by: Jeff Moyer Acked-by: Josef Bacik Cc: Christoph Hellwig Cc: Chris Mason Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/direct-io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/direct-io.c b/fs/direct-io.c index a10cb91cadea..458fdd360dda 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -634,7 +634,7 @@ static int dio_send_cur_page(struct dio *dio) int ret = 0; if (dio->bio) { - loff_t cur_offset = dio->block_in_file << dio->blkbits; + loff_t cur_offset = dio->cur_page_fs_offset; loff_t bio_next_offset = dio->logical_offset_in_bio + dio->bio->bi_size; @@ -659,7 +659,7 @@ static int dio_send_cur_page(struct dio *dio) * Submit now if the underlying fs is about to perform a * metadata read */ - if (dio->boundary) + else if (dio->boundary) dio_bio_submit(dio); } -- cgit v1.2.3 From b8536db269735d35d2b9a6480d40de212fed1b3c Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 23 Aug 2010 16:50:12 +0800 Subject: tracing: Fix a race in function profile commit 3aaba20f26f58843e8f20611e5c0b1c06954310f upstream. While we are reading trace_stat/functionX and someone just disabled function_profile at that time, we can trigger this: divide error: 0000 [#1] PREEMPT SMP ... EIP is at function_stat_show+0x90/0x230 ... This fix just takes the ftrace_profile_lock and checks if rec->counter is 0. If it's 0, we know the profile buffer has been reset. Signed-off-by: Li Zefan LKML-Reference: <4C723644.4040708@cn.fujitsu.com> Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/trace/ftrace.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 6d2cb14f9449..83836650e54b 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -381,12 +381,19 @@ static int function_stat_show(struct seq_file *m, void *v) { struct ftrace_profile *rec = v; char str[KSYM_SYMBOL_LEN]; + int ret = 0; #ifdef CONFIG_FUNCTION_GRAPH_TRACER - static DEFINE_MUTEX(mutex); static struct trace_seq s; unsigned long long avg; unsigned long long stddev; #endif + mutex_lock(&ftrace_profile_lock); + + /* we raced with function_profile_reset() */ + if (unlikely(rec->counter == 0)) { + ret = -EBUSY; + goto out; + } kallsyms_lookup(rec->ip, NULL, NULL, NULL, str); seq_printf(m, " %-30.30s %10lu", str, rec->counter); @@ -408,7 +415,6 @@ static int function_stat_show(struct seq_file *m, void *v) do_div(stddev, (rec->counter - 1) * 1000); } - mutex_lock(&mutex); trace_seq_init(&s); trace_print_graph_duration(rec->time, &s); trace_seq_puts(&s, " "); @@ -416,11 +422,12 @@ static int function_stat_show(struct seq_file *m, void *v) trace_seq_puts(&s, " "); trace_print_graph_duration(stddev, &s); trace_print_seq(m, &s); - mutex_unlock(&mutex); #endif seq_putc(m, '\n'); +out: + mutex_unlock(&ftrace_profile_lock); - return 0; + return ret; } static void ftrace_profile_reset(struct ftrace_profile_stat *stat) -- cgit v1.2.3 From 3c3d2da76db54975593ef526cbb17b94054c0fa2 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 8 Sep 2010 11:20:37 -0400 Subject: tracing: Do not allow llseek to set_ftrace_filter commit 9c55cb12c1c172e2d51e85fbb5a4796ca86b77e7 upstream. Reading the file set_ftrace_filter does three things. 1) shows whether or not filters are set for the function tracer 2) shows what functions are set for the function tracer 3) shows what triggers are set on any functions 3 is independent from 1 and 2. The way this file currently works is that it is a state machine, and as you read it, it may change state. But this assumption breaks when you use lseek() on the file. The state machine gets out of sync and the t_show() may use the wrong pointer and cause a kernel oops. Luckily, this will only kill the app that does the lseek, but the app dies while holding a mutex. This prevents anyone else from using the set_ftrace_filter file (or any other function tracing file for that matter). A real fix for this is to rewrite the code, but that is too much for a -rc release or stable. This patch simply disables llseek on the set_ftrace_filter() file for now, and we can do the proper fix for the next major release. Reported-by: Robert Swiecki Cc: Chris Wright Cc: Tavis Ormandy Cc: Eugene Teo Cc: vendor-sec@lst.de Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/trace/ftrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 83836650e54b..67b9a3a43a20 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -2417,7 +2417,7 @@ static const struct file_operations ftrace_filter_fops = { .open = ftrace_filter_open, .read = seq_read, .write = ftrace_filter_write, - .llseek = ftrace_regex_lseek, + .llseek = no_llseek, .release = ftrace_filter_release, }; -- cgit v1.2.3 From 1b8c931cecdda5ce851b206e7dae5ff4470ec125 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Thu, 9 Sep 2010 16:34:59 -0700 Subject: tracing: t_start: reset FTRACE_ITER_HASH in case of seek/pread commit df09162550fbb53354f0c88e85b5d0e6129ee9cc upstream. Be sure to avoid entering t_show() with FTRACE_ITER_HASH set without having properly started the iterator to iterate the hash. This case is degenerate and, as discovered by Robert Swiecki, can cause t_hash_show() to misuse a pointer. This causes a NULL ptr deref with possible security implications. Tracked as CVE-2010-3079. Cc: Robert Swiecki Cc: Eugene Teo Signed-off-by: Chris Wright Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/trace/ftrace.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 67b9a3a43a20..6b316b3928a3 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1510,6 +1510,8 @@ static void *t_start(struct seq_file *m, loff_t *pos) if (*pos > 0) return t_hash_start(m, pos); iter->flags |= FTRACE_ITER_PRINTALL; + /* reset in case of seek/pread */ + iter->flags &= ~FTRACE_ITER_HASH; return iter; } -- cgit v1.2.3 From edcc17148783ddd92a0e23c1a8ae3282607b1220 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 4 Sep 2010 03:14:35 +0000 Subject: irda: off by one commit cf9b94f88bdbe8a02015fc30d7c232b2d262d4ad upstream. This is an off by one. We would go past the end when we NUL terminate the "value" string at end of the function. The "value" buffer is allocated in irlan_client_parse_response() or irlan_provider_parse_command(). CC: stable@kernel.org Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- net/irda/irlan/irlan_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index a788f9e9427d..6130f9d9dbe1 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c @@ -1102,7 +1102,7 @@ int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len) memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */ le16_to_cpus(&val_len); n+=2; - if (val_len > 1016) { + if (val_len >= 1016) { IRDA_DEBUG(2, "%s(), parameter length to long\n", __func__ ); return -RSP_INVALID_COMMAND_FORMAT; } -- cgit v1.2.3 From 8417544f5bba23a210528125af2c4fa04f5e1683 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 9 Sep 2010 16:37:31 -0700 Subject: hp_accel: add quirks for HP ProBook 532x and HP Mini 5102 commit 4e70598c3b56e6fec551454c495d4d4025834749 upstream. Added missing axis-mapping for HP ProBook 532x and HP Mini 5102. Signed-off-by: Takashi Iwai Cc: Eric Piel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/hp_accel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c index 7580f55e67e3..36e957532230 100644 --- a/drivers/hwmon/hp_accel.c +++ b/drivers/hwmon/hp_accel.c @@ -221,6 +221,8 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { AXIS_DMI_MATCH("HPB442x", "HP ProBook 442", xy_rotated_left), AXIS_DMI_MATCH("HPB452x", "HP ProBook 452", y_inverted), AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap), + AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted), + AXIS_DMI_MATCH("Mini5102", "HP Mini 5102", xy_rotated_left_usd), { NULL, } /* Laptop models without axis info (yet): * "NC6910" "HP Compaq 6910" -- cgit v1.2.3 From b2f62d51745043996a75a45ba9e40b4be9595332 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Thu, 9 Sep 2010 16:37:35 -0700 Subject: gcov: fix null-pointer dereference for certain module types commit 85a0fdfd0f967507f3903e8419bc7e408f5a59de upstream. The gcov-kernel infrastructure expects that each object file is loaded only once. This may not be true, e.g. when loading multiple kernel modules which are linked to the same object file. As a result, loading such kernel modules will result in incorrect gcov results while unloading will cause a null-pointer dereference. This patch fixes these problems by changing the gcov-kernel infrastructure so that multiple profiling data sets can be associated with one debugfs entry. It applies to 2.6.36-rc1. Signed-off-by: Peter Oberparleiter Reported-by: Werner Spies Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/gcov/fs.c | 244 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 180 insertions(+), 64 deletions(-) diff --git a/kernel/gcov/fs.c b/kernel/gcov/fs.c index ef3c3f88a7a3..f83972b16564 100644 --- a/kernel/gcov/fs.c +++ b/kernel/gcov/fs.c @@ -33,10 +33,11 @@ * @children: child nodes * @all: list head for list of all nodes * @parent: parent node - * @info: associated profiling data structure if not a directory - * @ghost: when an object file containing profiling data is unloaded we keep a - * copy of the profiling data here to allow collecting coverage data - * for cleanup code. Such a node is called a "ghost". + * @loaded_info: array of pointers to profiling data sets for loaded object + * files. + * @num_loaded: number of profiling data sets for loaded object files. + * @unloaded_info: accumulated copy of profiling data sets for unloaded + * object files. Used only when gcov_persist=1. * @dentry: main debugfs entry, either a directory or data file * @links: associated symbolic links * @name: data file basename @@ -51,10 +52,11 @@ struct gcov_node { struct list_head children; struct list_head all; struct gcov_node *parent; - struct gcov_info *info; - struct gcov_info *ghost; + struct gcov_info **loaded_info; + struct gcov_info *unloaded_info; struct dentry *dentry; struct dentry **links; + int num_loaded; char name[0]; }; @@ -136,16 +138,37 @@ static const struct seq_operations gcov_seq_ops = { }; /* - * Return the profiling data set for a given node. This can either be the - * original profiling data structure or a duplicate (also called "ghost") - * in case the associated object file has been unloaded. + * Return a profiling data set associated with the given node. This is + * either a data set for a loaded object file or a data set copy in case + * all associated object files have been unloaded. */ static struct gcov_info *get_node_info(struct gcov_node *node) { - if (node->info) - return node->info; + if (node->num_loaded > 0) + return node->loaded_info[0]; - return node->ghost; + return node->unloaded_info; +} + +/* + * Return a newly allocated profiling data set which contains the sum of + * all profiling data associated with the given node. + */ +static struct gcov_info *get_accumulated_info(struct gcov_node *node) +{ + struct gcov_info *info; + int i = 0; + + if (node->unloaded_info) + info = gcov_info_dup(node->unloaded_info); + else + info = gcov_info_dup(node->loaded_info[i++]); + if (!info) + return NULL; + for (; i < node->num_loaded; i++) + gcov_info_add(info, node->loaded_info[i]); + + return info; } /* @@ -163,9 +186,10 @@ static int gcov_seq_open(struct inode *inode, struct file *file) mutex_lock(&node_lock); /* * Read from a profiling data copy to minimize reference tracking - * complexity and concurrent access. + * complexity and concurrent access and to keep accumulating multiple + * profiling data sets associated with one node simple. */ - info = gcov_info_dup(get_node_info(node)); + info = get_accumulated_info(node); if (!info) goto out_unlock; iter = gcov_iter_new(info); @@ -225,12 +249,25 @@ static struct gcov_node *get_node_by_name(const char *name) return NULL; } +/* + * Reset all profiling data associated with the specified node. + */ +static void reset_node(struct gcov_node *node) +{ + int i; + + if (node->unloaded_info) + gcov_info_reset(node->unloaded_info); + for (i = 0; i < node->num_loaded; i++) + gcov_info_reset(node->loaded_info[i]); +} + static void remove_node(struct gcov_node *node); /* * write() implementation for gcov data files. Reset profiling data for the - * associated file. If the object file has been unloaded (i.e. this is - * a "ghost" node), remove the debug fs node as well. + * corresponding file. If all associated object files have been unloaded, + * remove the debug fs node as well. */ static ssize_t gcov_seq_write(struct file *file, const char __user *addr, size_t len, loff_t *pos) @@ -245,10 +282,10 @@ static ssize_t gcov_seq_write(struct file *file, const char __user *addr, node = get_node_by_name(info->filename); if (node) { /* Reset counts or remove node for unloaded modules. */ - if (node->ghost) + if (node->num_loaded == 0) remove_node(node); else - gcov_info_reset(node->info); + reset_node(node); } /* Reset counts for open file. */ gcov_info_reset(info); @@ -378,7 +415,10 @@ static void init_node(struct gcov_node *node, struct gcov_info *info, INIT_LIST_HEAD(&node->list); INIT_LIST_HEAD(&node->children); INIT_LIST_HEAD(&node->all); - node->info = info; + if (node->loaded_info) { + node->loaded_info[0] = info; + node->num_loaded = 1; + } node->parent = parent; if (name) strcpy(node->name, name); @@ -394,9 +434,13 @@ static struct gcov_node *new_node(struct gcov_node *parent, struct gcov_node *node; node = kzalloc(sizeof(struct gcov_node) + strlen(name) + 1, GFP_KERNEL); - if (!node) { - pr_warning("out of memory\n"); - return NULL; + if (!node) + goto err_nomem; + if (info) { + node->loaded_info = kcalloc(1, sizeof(struct gcov_info *), + GFP_KERNEL); + if (!node->loaded_info) + goto err_nomem; } init_node(node, info, name, parent); /* Differentiate between gcov data file nodes and directory nodes. */ @@ -416,6 +460,11 @@ static struct gcov_node *new_node(struct gcov_node *parent, list_add(&node->all, &all_head); return node; + +err_nomem: + kfree(node); + pr_warning("out of memory\n"); + return NULL; } /* Remove symbolic links associated with node. */ @@ -441,8 +490,9 @@ static void release_node(struct gcov_node *node) list_del(&node->all); debugfs_remove(node->dentry); remove_links(node); - if (node->ghost) - gcov_info_free(node->ghost); + kfree(node->loaded_info); + if (node->unloaded_info) + gcov_info_free(node->unloaded_info); kfree(node); } @@ -477,7 +527,7 @@ static struct gcov_node *get_child_by_name(struct gcov_node *parent, /* * write() implementation for reset file. Reset all profiling data to zero - * and remove ghost nodes. + * and remove nodes for which all associated object files are unloaded. */ static ssize_t reset_write(struct file *file, const char __user *addr, size_t len, loff_t *pos) @@ -487,8 +537,8 @@ static ssize_t reset_write(struct file *file, const char __user *addr, mutex_lock(&node_lock); restart: list_for_each_entry(node, &all_head, all) { - if (node->info) - gcov_info_reset(node->info); + if (node->num_loaded > 0) + reset_node(node); else if (list_empty(&node->children)) { remove_node(node); /* Several nodes may have gone - restart loop. */ @@ -564,37 +614,115 @@ err_remove: } /* - * The profiling data set associated with this node is being unloaded. Store a - * copy of the profiling data and turn this node into a "ghost". + * Associate a profiling data set with an existing node. Needs to be called + * with node_lock held. */ -static int ghost_node(struct gcov_node *node) +static void add_info(struct gcov_node *node, struct gcov_info *info) { - node->ghost = gcov_info_dup(node->info); - if (!node->ghost) { - pr_warning("could not save data for '%s' (out of memory)\n", - node->info->filename); - return -ENOMEM; + struct gcov_info **loaded_info; + int num = node->num_loaded; + + /* + * Prepare new array. This is done first to simplify cleanup in + * case the new data set is incompatible, the node only contains + * unloaded data sets and there's not enough memory for the array. + */ + loaded_info = kcalloc(num + 1, sizeof(struct gcov_info *), GFP_KERNEL); + if (!loaded_info) { + pr_warning("could not add '%s' (out of memory)\n", + info->filename); + return; + } + memcpy(loaded_info, node->loaded_info, + num * sizeof(struct gcov_info *)); + loaded_info[num] = info; + /* Check if the new data set is compatible. */ + if (num == 0) { + /* + * A module was unloaded, modified and reloaded. The new + * data set replaces the copy of the last one. + */ + if (!gcov_info_is_compatible(node->unloaded_info, info)) { + pr_warning("discarding saved data for %s " + "(incompatible version)\n", info->filename); + gcov_info_free(node->unloaded_info); + node->unloaded_info = NULL; + } + } else { + /* + * Two different versions of the same object file are loaded. + * The initial one takes precedence. + */ + if (!gcov_info_is_compatible(node->loaded_info[0], info)) { + pr_warning("could not add '%s' (incompatible " + "version)\n", info->filename); + kfree(loaded_info); + return; + } } - node->info = NULL; + /* Overwrite previous array. */ + kfree(node->loaded_info); + node->loaded_info = loaded_info; + node->num_loaded = num + 1; +} - return 0; +/* + * Return the index of a profiling data set associated with a node. + */ +static int get_info_index(struct gcov_node *node, struct gcov_info *info) +{ + int i; + + for (i = 0; i < node->num_loaded; i++) { + if (node->loaded_info[i] == info) + return i; + } + return -ENOENT; } /* - * Profiling data for this node has been loaded again. Add profiling data - * from previous instantiation and turn this node into a regular node. + * Save the data of a profiling data set which is being unloaded. */ -static void revive_node(struct gcov_node *node, struct gcov_info *info) +static void save_info(struct gcov_node *node, struct gcov_info *info) { - if (gcov_info_is_compatible(node->ghost, info)) - gcov_info_add(info, node->ghost); + if (node->unloaded_info) + gcov_info_add(node->unloaded_info, info); else { - pr_warning("discarding saved data for '%s' (version changed)\n", + node->unloaded_info = gcov_info_dup(info); + if (!node->unloaded_info) { + pr_warning("could not save data for '%s' " + "(out of memory)\n", info->filename); + } + } +} + +/* + * Disassociate a profiling data set from a node. Needs to be called with + * node_lock held. + */ +static void remove_info(struct gcov_node *node, struct gcov_info *info) +{ + int i; + + i = get_info_index(node, info); + if (i < 0) { + pr_warning("could not remove '%s' (not found)\n", info->filename); + return; } - gcov_info_free(node->ghost); - node->ghost = NULL; - node->info = info; + if (gcov_persist) + save_info(node, info); + /* Shrink array. */ + node->loaded_info[i] = node->loaded_info[node->num_loaded - 1]; + node->num_loaded--; + if (node->num_loaded > 0) + return; + /* Last loaded data set was removed. */ + kfree(node->loaded_info); + node->loaded_info = NULL; + node->num_loaded = 0; + if (!node->unloaded_info) + remove_node(node); } /* @@ -609,30 +737,18 @@ void gcov_event(enum gcov_action action, struct gcov_info *info) node = get_node_by_name(info->filename); switch (action) { case GCOV_ADD: - /* Add new node or revive ghost. */ - if (!node) { + if (node) + add_info(node, info); + else add_node(info); - break; - } - if (gcov_persist) - revive_node(node, info); - else { - pr_warning("could not add '%s' (already exists)\n", - info->filename); - } break; case GCOV_REMOVE: - /* Remove node or turn into ghost. */ - if (!node) { + if (node) + remove_info(node, info); + else { pr_warning("could not remove '%s' (not found)\n", info->filename); - break; } - if (gcov_persist) { - if (!ghost_node(node)) - break; - } - remove_node(node); break; } mutex_unlock(&node_lock); -- cgit v1.2.3 From 99e2e17956364653157150b8304ee3565539338e Mon Sep 17 00:00:00 2001 From: Yusuke Goda Date: Thu, 9 Sep 2010 16:37:39 -0700 Subject: tmio_mmc: don't clear unhandled pending interrupts commit b78d6c5f51935ba89df8db33a57bacb547aa7325 upstream. Previously, it was possible for ack_mmc_irqs() to clear pending interrupt bits in the CTL_STATUS register, even though the interrupt handler had not been called. This was because of a race that existed when doing a read-modify-write sequence on CTL_STATUS. After the read step in this sequence, if an interrupt occurred (causing one of the bits in CTL_STATUS to be set) the write step would inadvertently clear it. Observed with the TMIO_STAT_RXRDY bit together with CMD53 on AR6002 and BCM4318 SDIO cards in polled mode. This patch eliminates this race by only writing to CTL_STATUS and clearing the interrupts that were passed as an argument to ack_mmc_irqs()." [matt@console-pimps.org: rewrote changelog] Signed-off-by: Yusuke Goda Acked-by: Magnus Damm Tested-by: Arnd Hannemann " Acked-by: Ian Molton Cc: Matt Fleming Cc: Samuel Ortiz Cc: Paul Mundt Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/tmio_mmc.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 64f7d5dfc106..79446047ee78 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -82,10 +82,7 @@ #define ack_mmc_irqs(host, i) \ do { \ - u32 mask;\ - mask = sd_ctrl_read32((host), CTL_STATUS); \ - mask &= ~((i) & TMIO_MASK_IRQ); \ - sd_ctrl_write32((host), CTL_STATUS, mask); \ + sd_ctrl_write32((host), CTL_STATUS, ~(i)); \ } while (0) -- cgit v1.2.3 From 77dc28848881926ba46e9b6bb9f64fb71d61bddc Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 9 Sep 2010 16:37:43 -0700 Subject: mmc: fix the use of kunmap_atomic() in tmio_mmc.h commit 5600efb1bc2745d93ae0bc08130117a84f2b9d69 upstream. kunmap_atomic() takes the cookie, returned by the kmap_atomic() as its argument and not the page address, used as an argument to kmap_atomic(). This patch fixes the compile error: In file included from drivers/mmc/host/tmio_mmc.c:37: drivers/mmc/host/tmio_mmc.h: In function 'tmio_mmc_kunmap_atomic': drivers/mmc/host/tmio_mmc.h:192: error: negative width in bit-field '' Signed-off-by: Guennadi Liakhovetski Acked-by: Eric Miao Tested-by: Magnus Damm Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/tmio_mmc.c | 7 ++++--- drivers/mmc/host/tmio_mmc.h | 8 +++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index ee7d0a5a51c4..69d98e3bf6ab 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -164,6 +164,7 @@ tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command *cmd) static void tmio_mmc_pio_irq(struct tmio_mmc_host *host) { struct mmc_data *data = host->data; + void *sg_virt; unsigned short *buf; unsigned int count; unsigned long flags; @@ -173,8 +174,8 @@ static void tmio_mmc_pio_irq(struct tmio_mmc_host *host) return; } - buf = (unsigned short *)(tmio_mmc_kmap_atomic(host, &flags) + - host->sg_off); + sg_virt = tmio_mmc_kmap_atomic(host->sg_ptr, &flags); + buf = (unsigned short *)(sg_virt + host->sg_off); count = host->sg_ptr->length - host->sg_off; if (count > data->blksz) @@ -191,7 +192,7 @@ static void tmio_mmc_pio_irq(struct tmio_mmc_host *host) host->sg_off += count; - tmio_mmc_kunmap_atomic(host, &flags); + tmio_mmc_kunmap_atomic(sg_virt, &flags); if (host->sg_off == host->sg_ptr->length) tmio_mmc_next_sg(host); diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 79446047ee78..0fedc78e3ea5 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -174,19 +174,17 @@ static inline int tmio_mmc_next_sg(struct tmio_mmc_host *host) return --host->sg_len; } -static inline char *tmio_mmc_kmap_atomic(struct tmio_mmc_host *host, +static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg, unsigned long *flags) { - struct scatterlist *sg = host->sg_ptr; - local_irq_save(*flags); return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; } -static inline void tmio_mmc_kunmap_atomic(struct tmio_mmc_host *host, +static inline void tmio_mmc_kunmap_atomic(void *virt, unsigned long *flags) { - kunmap_atomic(sg_page(host->sg_ptr), KM_BIO_SRC_IRQ); + kunmap_atomic(virt, KM_BIO_SRC_IRQ); local_irq_restore(*flags); } -- cgit v1.2.3 From 094b59b2cff1d17310037e957c7e343921d86aaa Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Tue, 10 Aug 2010 18:01:41 -0700 Subject: mmc: fix all hangs related to mmc/sd card insert/removal during suspend/resume commit 4c2ef25fe0b847d2ae818f74758ddb0be1c27d8e upstream. If you don't use CONFIG_MMC_UNSAFE_RESUME, as soon as you attempt to suspend, the card will be removed, therefore this patch doesn't change the behavior of this option. However the removal will be done by pm notifier, which runs while userspace is still not frozen and thus can freely use del_gendisk, without the risk of deadlock which would happen otherwise. Card detect workqueue is now disabled while userspace is frozen, Therefore if you do use CONFIG_MMC_UNSAFE_RESUME, and remove the card during suspend, the removal will be detected as soon as userspace is unfrozen, again at the moment it is safe to call del_gendisk. Tested with and without CONFIG_MMC_UNSAFE_RESUME with suspend and hibernate. [akpm@linux-foundation.org: clean up function prototype] [akpm@linux-foundation.org: fix CONFIG_PM-n linkage, small cleanups] [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Maxim Levitsky Cc: David Brownell Cc: Alan Stern Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Lee Jones Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/core/core.c | 83 +++++++++++++++++++++++++++++++++--------------- drivers/mmc/core/host.c | 4 +++ include/linux/mmc/host.h | 3 ++ 3 files changed, 64 insertions(+), 26 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 569e94da844c..83e7543b55d9 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1057,6 +1057,17 @@ void mmc_rescan(struct work_struct *work) container_of(work, struct mmc_host, detect.work); u32 ocr; int err; + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + + if (host->rescan_disable) { + spin_unlock_irqrestore(&host->lock, flags); + return; + } + + spin_unlock_irqrestore(&host->lock, flags); + mmc_bus_get(host); @@ -1266,19 +1277,6 @@ int mmc_suspend_host(struct mmc_host *host) if (host->bus_ops && !host->bus_dead) { if (host->bus_ops->suspend) err = host->bus_ops->suspend(host); - if (err == -ENOSYS || !host->bus_ops->resume) { - /* - * We simply "remove" the card in this case. - * It will be redetected on resume. - */ - if (host->bus_ops->remove) - host->bus_ops->remove(host); - mmc_claim_host(host); - mmc_detach_bus(host); - mmc_release_host(host); - host->pm_flags = 0; - err = 0; - } } mmc_bus_put(host); @@ -1310,28 +1308,61 @@ int mmc_resume_host(struct mmc_host *host) printk(KERN_WARNING "%s: error %d during resume " "(card was removed?)\n", mmc_hostname(host), err); - if (host->bus_ops->remove) - host->bus_ops->remove(host); - mmc_claim_host(host); - mmc_detach_bus(host); - mmc_release_host(host); - /* no need to bother upper layers */ err = 0; } } mmc_bus_put(host); - /* - * We add a slight delay here so that resume can progress - * in parallel. - */ - mmc_detect_change(host, 1); - return err; } - EXPORT_SYMBOL(mmc_resume_host); +/* Do the card removal on suspend if card is assumed removeable + * Do that in pm notifier while userspace isn't yet frozen, so we will be able + to sync the card. +*/ +int mmc_pm_notify(struct notifier_block *notify_block, + unsigned long mode, void *unused) +{ + struct mmc_host *host = container_of( + notify_block, struct mmc_host, pm_notify); + unsigned long flags; + + + switch (mode) { + case PM_HIBERNATION_PREPARE: + case PM_SUSPEND_PREPARE: + + spin_lock_irqsave(&host->lock, flags); + host->rescan_disable = 1; + spin_unlock_irqrestore(&host->lock, flags); + cancel_delayed_work_sync(&host->detect); + + if (!host->bus_ops || host->bus_ops->suspend) + break; + + mmc_claim_host(host); + + if (host->bus_ops->remove) + host->bus_ops->remove(host); + + mmc_detach_bus(host); + mmc_release_host(host); + host->pm_flags = 0; + break; + + case PM_POST_SUSPEND: + case PM_POST_HIBERNATION: + + spin_lock_irqsave(&host->lock, flags); + host->rescan_disable = 0; + spin_unlock_irqrestore(&host->lock, flags); + mmc_detect_change(host, 0); + + } + + return 0; +} #endif static int __init mmc_init(void) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 47353909e345..0efe631e50ca 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -85,6 +86,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) init_waitqueue_head(&host->wq); INIT_DELAYED_WORK(&host->detect, mmc_rescan); INIT_DELAYED_WORK_DEFERRABLE(&host->disable, mmc_host_deeper_disable); + host->pm_notify.notifier_call = mmc_pm_notify; /* * By default, hosts do not support SGIO or large requests. @@ -133,6 +135,7 @@ int mmc_add_host(struct mmc_host *host) #endif mmc_start_host(host); + register_pm_notifier(&host->pm_notify); return 0; } @@ -149,6 +152,7 @@ EXPORT_SYMBOL(mmc_add_host); */ void mmc_remove_host(struct mmc_host *host) { + unregister_pm_notifier(&host->pm_notify); mmc_stop_host(host); #ifdef CONFIG_DEBUG_FS diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index f65913c9f5a4..513ff0376b09 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -124,6 +124,7 @@ struct mmc_host { unsigned int f_min; unsigned int f_max; u32 ocr_avail; + struct notifier_block pm_notify; #define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */ #define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */ @@ -183,6 +184,7 @@ struct mmc_host { /* Only used with MMC_CAP_DISABLE */ int enabled; /* host is enabled */ + int rescan_disable; /* disable card detection */ int nesting_cnt; /* "enable" nesting count */ int en_dis_recurs; /* detect recursion */ unsigned int disable_delay; /* disable delay in msecs */ @@ -257,6 +259,7 @@ int mmc_card_can_sleep(struct mmc_host *host); int mmc_host_enable(struct mmc_host *host); int mmc_host_disable(struct mmc_host *host); int mmc_host_lazy_disable(struct mmc_host *host); +int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *); static inline void mmc_set_disable_delay(struct mmc_host *host, unsigned int disable_delay) -- cgit v1.2.3 From e921923ed257d47c720f4fd71eeed812c4f5af9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 18 Aug 2010 09:25:38 -0700 Subject: mmc: build fix: mmc_pm_notify is only available with CONFIG_PM=y MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 81ca03a0e2ea0207b2df80e0edcf4c775c07a505 upstream. This fixes a build breakage introduced by commit 4c2ef25fe0b8 ("mmc: fix all hangs related to mmc/sd card insert/removal during suspend/resume") Cc: David Brownell Cc: Alan Stern Cc: linux-mmc@vger.kernel.org Cc: Andrew Morton Signed-off-by: Uwe Kleine-König Acked-by: Kukjin Kim Acked-by: Maxim Levitsky Acked-by: Randy Dunlap Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/core/host.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 0efe631e50ca..d80cfdc8edd2 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -86,7 +86,9 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) init_waitqueue_head(&host->wq); INIT_DELAYED_WORK(&host->detect, mmc_rescan); INIT_DELAYED_WORK_DEFERRABLE(&host->disable, mmc_host_deeper_disable); +#ifdef CONFIG_PM host->pm_notify.notifier_call = mmc_pm_notify; +#endif /* * By default, hosts do not support SGIO or large requests. -- cgit v1.2.3 From bcedd390d037d0e3b43da97a86e37a9bb7ceac91 Mon Sep 17 00:00:00 2001 From: Menyhart Zoltan Date: Sun, 12 Sep 2010 19:55:26 -0400 Subject: statfs() gives ESTALE error commit fbf3fdd2443965d9ba6fb4b5fecd1f6e0847218f upstream. Hi, An NFS client executes a statfs("file", &buff) call. "file" exists / existed, the client has read / written it, but it has already closed it. user_path(pathname, &path) looks up "file" successfully in the directory-cache and restarts the aging timer of the directory-entry. Even if "file" has already been removed from the server, because the lookupcache=positive option I use, keeps the entries valid for a while. nfs_statfs() returns ESTALE if "file" has already been removed from the server. If the user application repeats the statfs("file", &buff) call, we are stuck: "file" remains young forever in the directory-cache. Signed-off-by: Zoltan Menyhart Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/super.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 6bf11d745a3f..381d9291ea17 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -431,7 +431,15 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) goto out_err; error = server->nfs_client->rpc_ops->statfs(server, fh, &res); + if (unlikely(error == -ESTALE)) { + struct dentry *pd_dentry; + pd_dentry = dget_parent(dentry); + if (pd_dentry != NULL) { + nfs_zap_caches(pd_dentry->d_inode); + dput(pd_dentry); + } + } nfs_free_fattr(res.fattr); if (error < 0) goto out_err; -- cgit v1.2.3 From b49853780d6aaf8a5cccf6667648e428719f8f3e Mon Sep 17 00:00:00 2001 From: "Jorge Boncompte [DTI2]" Date: Thu, 9 Sep 2010 16:38:19 -0700 Subject: minix: fix regression in minix_mkdir() commit eee743fd7eac9f2ea69ad06d093dfb5a12538fe5 upstream. Commit 9eed1fb721c ("minix: replace inode uid,gid,mode init with helper") broke directory creation on minix filesystems. Fix it by passing the needed mode flag to inode init helper. Signed-off-by: Jorge Boncompte [DTI2] Cc: Dmitry Monakhov Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/minix/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/minix/namei.c b/fs/minix/namei.c index e20ee85955d1..f3f3578393a4 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -115,7 +115,7 @@ static int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode) inode_inc_link_count(dir); - inode = minix_new_inode(dir, mode, &err); + inode = minix_new_inode(dir, S_IFDIR | mode, &err); if (!inode) goto out_dir; -- cgit v1.2.3 From cfa7e5c5fce001efa3d35c84229aec67ae6ade7a Mon Sep 17 00:00:00 2001 From: Gary King Date: Thu, 9 Sep 2010 16:38:05 -0700 Subject: bounce: call flush_dcache_page() after bounce_copy_vec() commit ac8456d6f9a3011c824176bd6084d39e5f70a382 upstream. I have been seeing problems on Tegra 2 (ARMv7 SMP) systems with HIGHMEM enabled on 2.6.35 (plus some patches targetted at 2.6.36 to perform cache maintenance lazily), and the root cause appears to be that the mm bouncing code is calling flush_dcache_page before it copies the bounce buffer into the bio. The bounced page needs to be flushed after data is copied into it, to ensure that architecture implementations can synchronize instruction and data caches if necessary. Signed-off-by: Gary King Cc: Tejun Heo Cc: Russell King Acked-by: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/bounce.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/bounce.c b/mm/bounce.c index 13b6dad1eed2..1481de68184b 100644 --- a/mm/bounce.c +++ b/mm/bounce.c @@ -116,8 +116,8 @@ static void copy_to_high_bio_irq(struct bio *to, struct bio *from) */ vfrom = page_address(fromvec->bv_page) + tovec->bv_offset; - flush_dcache_page(tovec->bv_page); bounce_copy_vec(tovec, vfrom); + flush_dcache_page(tovec->bv_page); } } -- cgit v1.2.3 From 5b253de765e92893bd5431ed995e3ca58bac274c Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Thu, 9 Sep 2010 16:38:00 -0700 Subject: mm: compaction: handle active and inactive fairly in too_many_isolated commit bc6930457460788e14b2c0808ed4632a1592bd61 upstream. Iram reported that compaction's too_many_isolated() loops forever. (http://www.spinics.net/lists/linux-mm/msg08123.html) The meminfo when the situation happened was inactive anon is zero. That's because the system has no memory pressure until then. While all anon pages were in the active lru, compaction could select active lru as well as inactive lru. That's a different thing from vmscan's isolated. So we has been two too_many_isolated. While compaction can isolate pages in both active and inactive, current implementation of too_many_isolated only considers inactive. It made Iram's problem. This patch handles active and inactive fairly. That's because we can't expect where from and how many compaction would isolated pages. This patch changes (nr_isolated > nr_inactive) with nr_isolated > (nr_active + nr_inactive) / 2. Signed-off-by: Minchan Kim Reported-by: Iram Shahzad Acked-by: Mel Gorman Acked-by: Wu Fengguang Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/compaction.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mm/compaction.c b/mm/compaction.c index 94cce51b0b35..4d709ee59013 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -214,15 +214,16 @@ static void acct_isolated(struct zone *zone, struct compact_control *cc) /* Similar to reclaim, but different enough that they don't share logic */ static bool too_many_isolated(struct zone *zone) { - - unsigned long inactive, isolated; + unsigned long active, inactive, isolated; inactive = zone_page_state(zone, NR_INACTIVE_FILE) + zone_page_state(zone, NR_INACTIVE_ANON); + active = zone_page_state(zone, NR_ACTIVE_FILE) + + zone_page_state(zone, NR_ACTIVE_ANON); isolated = zone_page_state(zone, NR_ISOLATED_FILE) + zone_page_state(zone, NR_ISOLATED_ANON); - return isolated > inactive; + return isolated > (inactive + active) / 2; } /* -- cgit v1.2.3 From 9eca1e9defb46502949e35d1c81ad98d682da9e5 Mon Sep 17 00:00:00 2001 From: Jerome Marchand Date: Thu, 9 Sep 2010 16:37:59 -0700 Subject: kernel/groups.c: fix integer overflow in groups_search commit 1c24de60e50fb19b94d94225458da17c720f0729 upstream. gid_t is a unsigned int. If group_info contains a gid greater than MAX_INT, groups_search() function may look on the wrong side of the search tree. This solves some unfair "permission denied" problems. Signed-off-by: Jerome Marchand Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/groups.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/kernel/groups.c b/kernel/groups.c index 53b1916c9492..253dc0f35cf4 100644 --- a/kernel/groups.c +++ b/kernel/groups.c @@ -143,10 +143,9 @@ int groups_search(const struct group_info *group_info, gid_t grp) right = group_info->ngroups; while (left < right) { unsigned int mid = (left+right)/2; - int cmp = grp - GROUP_AT(group_info, mid); - if (cmp > 0) + if (grp > GROUP_AT(group_info, mid)) left = mid + 1; - else if (cmp < 0) + else if (grp < GROUP_AT(group_info, mid)) right = mid; else return 1; -- cgit v1.2.3 From 964c3f00ecc7a6c789f7c9d0231ded4ab0ae1610 Mon Sep 17 00:00:00 2001 From: Jan Sembera Date: Thu, 9 Sep 2010 16:37:54 -0700 Subject: binfmt_misc: fix binfmt_misc priority commit ee3aebdd8f5f8eac41c25c80ceee3d728f920f3b upstream. Commit 74641f584da ("alpha: binfmt_aout fix") (May 2009) introduced a regression - binfmt_misc is now consulted after binfmt_elf, which will unfortunately break ia32el. ia32 ELF binaries on ia64 used to be matched using binfmt_misc and executed using wrapper. As 32bit binaries are now matched by binfmt_elf before bindmt_misc kicks in, the wrapper is ignored. The fix increases precedence of binfmt_misc to the original state. Signed-off-by: Jan Sembera Cc: Ivan Kokshaysky Cc: Al Viro Cc: Richard Henderson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/binfmt_misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index c4e83537ead7..42b60b04ea06 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -723,7 +723,7 @@ static int __init init_misc_binfmt(void) { int err = register_filesystem(&bm_fs_type); if (!err) { - err = register_binfmt(&misc_format); + err = insert_binfmt(&misc_format); if (err) unregister_filesystem(&bm_fs_type); } -- cgit v1.2.3 From e9d3ad84a2b475896c74e41036ba0e8b591fac8e Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 31 Aug 2010 17:27:02 -0700 Subject: Input: i8042 - fix device removal on unload commit af045b86662f17bf130239a65995c61a34f00a6b upstream. We need to call platform_device_unregister(i8042_platform_device) before calling platform_driver_unregister() because i8042_remove() resets i8042_platform_device to NULL. This leaves the platform device instance behind and prevents driver reload. Fixes https://bugzilla.kernel.org/show_bug.cgi?id=16613 Reported-by: Seryodkin Victor Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/serio/i8042.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 6440a8f55686..f3c2bb7eed43 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -1483,8 +1483,8 @@ static int __init i8042_init(void) static void __exit i8042_exit(void) { - platform_driver_unregister(&i8042_driver); platform_device_unregister(i8042_platform_device); + platform_driver_unregister(&i8042_driver); i8042_platform_exit(); panic_blink = NULL; -- cgit v1.2.3 From ac1a91ede75a5311e57b1a093d8b313cd7c9f515 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Jul 2010 20:25:34 -0700 Subject: Input: i8042 - reset keyboard controller wehen resuming from S2R commit 1ca56e513a9fd356d5a9e0de45dbe0e189e00386 upstream. Some laptops, such as Lenovo 3000 N100, require keyboard controller reset in order to have touchpad operable after suspend to RAM. Even if box does not need the reset it should be safe to do so, so instead of chasing after misbehaving boxes and grow DMI tables, let's reset the controller unconditionally. Reported-and-tested-by: Jerome Lacoste Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/serio/i8042.c | 65 ++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index f3c2bb7eed43..5d42358d0da6 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -861,9 +861,6 @@ static int i8042_controller_selftest(void) unsigned char param; int i = 0; - if (!i8042_reset) - return 0; - /* * We try this 5 times; on some really fragile systems this does not * take the first time... @@ -1020,7 +1017,8 @@ static void i8042_controller_reset(void) * Reset the controller if requested. */ - i8042_controller_selftest(); + if (i8042_reset) + i8042_controller_selftest(); /* * Restore the original control register setting. @@ -1093,24 +1091,12 @@ static void i8042_dritek_enable(void) #ifdef CONFIG_PM -/* - * Here we try to restore the original BIOS settings to avoid - * upsetting it. - */ - -static int i8042_pm_reset(struct device *dev) -{ - i8042_controller_reset(); - - return 0; -} - /* * Here we try to reset everything back to a state we had * before suspending. */ -static int i8042_pm_restore(struct device *dev) +static int i8042_controller_resume(bool force_reset) { int error; @@ -1118,9 +1104,11 @@ static int i8042_pm_restore(struct device *dev) if (error) return error; - error = i8042_controller_selftest(); - if (error) - return error; + if (i8042_reset || force_reset) { + error = i8042_controller_selftest(); + if (error) + return error; + } /* * Restore original CTR value and disable all ports @@ -1162,6 +1150,28 @@ static int i8042_pm_restore(struct device *dev) return 0; } +/* + * Here we try to restore the original BIOS settings to avoid + * upsetting it. + */ + +static int i8042_pm_reset(struct device *dev) +{ + i8042_controller_reset(); + + return 0; +} + +static int i8042_pm_resume(struct device *dev) +{ + /* + * On resume from S2R we always try to reset the controller + * to bring it in a sane state. (In case of S2D we expect + * BIOS to reset the controller for us.) + */ + return i8042_controller_resume(true); +} + static int i8042_pm_thaw(struct device *dev) { i8042_interrupt(0, NULL); @@ -1169,9 +1179,14 @@ static int i8042_pm_thaw(struct device *dev) return 0; } +static int i8042_pm_restore(struct device *dev) +{ + return i8042_controller_resume(false); +} + static const struct dev_pm_ops i8042_pm_ops = { .suspend = i8042_pm_reset, - .resume = i8042_pm_restore, + .resume = i8042_pm_resume, .thaw = i8042_pm_thaw, .poweroff = i8042_pm_reset, .restore = i8042_pm_restore, @@ -1389,9 +1404,11 @@ static int __init i8042_probe(struct platform_device *dev) i8042_platform_device = dev; - error = i8042_controller_selftest(); - if (error) - return error; + if (i8042_reset) { + error = i8042_controller_selftest(); + if (error) + return error; + } error = i8042_controller_init(); if (error) -- cgit v1.2.3 From 1d1a528b65f9c4f9f5f1bb2341aef6e4f3bfc5d1 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Thu, 9 Sep 2010 16:38:01 -0700 Subject: memory hotplug: fix next block calculation in is_removable commit 0dcc48c15f63ee86c2fcd33968b08d651f0360a5 upstream. next_active_pageblock() is for finding next _used_ freeblock. It skips several blocks when it finds there are a chunk of free pages lager than pageblock. But it has 2 bugs. 1. We have no lock. page_order(page) - pageblock_order can be minus. 2. pageblocks_stride += is wrong. it should skip page_order(p) of pages. Signed-off-by: KAMEZAWA Hiroyuki Cc: Michal Hocko Cc: Wu Fengguang Cc: Mel Gorman Cc: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/memory_hotplug.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index a4cfcdc00455..dd186c1a5d53 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -584,19 +584,19 @@ static inline int pageblock_free(struct page *page) /* Return the start of the next active pageblock after a given page */ static struct page *next_active_pageblock(struct page *page) { - int pageblocks_stride; - /* Ensure the starting page is pageblock-aligned */ BUG_ON(page_to_pfn(page) & (pageblock_nr_pages - 1)); - /* Move forward by at least 1 * pageblock_nr_pages */ - pageblocks_stride = 1; - /* If the entire pageblock is free, move to the end of free page */ - if (pageblock_free(page)) - pageblocks_stride += page_order(page) - pageblock_order; + if (pageblock_free(page)) { + int order; + /* be careful. we don't have locks, page_order can be changed.*/ + order = page_order(page); + if ((order < MAX_ORDER) && (order >= pageblock_order)) + return page + (1 << order); + } - return page + (pageblocks_stride * pageblock_nr_pages); + return page + pageblock_nr_pages; } /* Checks if this range of memory is likely to be hot-removable. */ -- cgit v1.2.3 From c0016ec4e51c5ae58dfbe15974192badf567b5f4 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sun, 22 Aug 2010 04:29:17 +0200 Subject: perf: Initialize callchains roots's childen hits commit 5225c45899e872383ca39f5533d28ec63c54b39e upstream. Each histogram entry has a callchain root that stores the callchain samples. However we forgot to initialize the tracking of children hits of these roots, which then got random values on their creation. The root children hits is multiplied by the minimum percentage of hits provided by the user, and the result becomes the minimum hits expected from children branches. If the random value due to the uninitialization is big enough, then this minimum number of hits can be huge and eventually filter every children branches. The end result was invisible callchains. All we need to fix this is to initialize the children hits of the root. Reported-by: Christoph Hellwig Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Signed-off-by: Greg Kroah-Hartman --- tools/perf/util/callchain.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index f2e9ee164bd8..ecb97329b63f 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -50,6 +50,7 @@ static inline void callchain_init(struct callchain_node *node) INIT_LIST_HEAD(&node->children); INIT_LIST_HEAD(&node->val); + node->children_hit = 0; node->parent = NULL; node->hit = 0; } -- cgit v1.2.3 From f4d60f54ed93f427219b359a1bbc29e2fc04cc67 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 10 Aug 2010 20:38:23 +0000 Subject: powerpc/perf_event: Reduce latency of calling perf_event_do_pending commit b0d278b7d3ae9115939ddcea93f516308cc367e2 upstream. Commit 0fe1ac48 ("powerpc/perf_event: Fix oops due to perf_event_do_pending call") moved the call to perf_event_do_pending in timer_interrupt() down so that it was after the irq_enter() call. Unfortunately this moved it after the code that checks whether it is time for the next decrementer clock event. The result is that the call to perf_event_do_pending() won't happen until the next decrementer clock event is due. This was pointed out by Milton Miller. This fixes it by moving the check for whether it's time for the next decrementer clock event down to the point where we're about to call the event handler, after we've called perf_event_do_pending. This has the side effect that on old pre-Core99 Powermacs where we use the ppc_n_lost_interrupts mechanism to replay interrupts, a replayed interrupt will incur a little more latency since it will now do the code from the irq_enter down to the irq_exit, that it used to skip. However, these machines are now old and rare enough that this doesn't matter. To make it clear that ppc_n_lost_interrupts is only used on Powermacs, and to speed up the code slightly on non-Powermac ppc32 machines, the code that tests ppc_n_lost_interrupts is now conditional on CONFIG_PMAC as well as CONFIG_PPC32. Signed-off-by: Paul Mackerras Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/time.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 0441bbdadbd1..b119497eb3b3 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -616,20 +616,11 @@ void timer_interrupt(struct pt_regs * regs) * some CPUs will continuue to take decrementer exceptions */ set_dec(DECREMENTER_MAX); -#ifdef CONFIG_PPC32 +#if defined(CONFIG_PPC32) && defined(CONFIG_PMAC) if (atomic_read(&ppc_n_lost_interrupts) != 0) do_IRQ(regs); #endif - now = get_tb_or_rtc(); - if (now < decrementer->next_tb) { - /* not time for this event yet */ - now = decrementer->next_tb - now; - if (now <= DECREMENTER_MAX) - set_dec((int)now); - trace_timer_interrupt_exit(regs); - return; - } old_regs = set_irq_regs(regs); irq_enter(); @@ -645,8 +636,16 @@ void timer_interrupt(struct pt_regs * regs) get_lppaca()->int_dword.fields.decr_int = 0; #endif - if (evt->event_handler) - evt->event_handler(evt); + now = get_tb_or_rtc(); + if (now >= decrementer->next_tb) { + decrementer->next_tb = ~(u64)0; + if (evt->event_handler) + evt->event_handler(evt); + } else { + now = decrementer->next_tb - now; + if (now <= DECREMENTER_MAX) + set_dec((int)now); + } #ifdef CONFIG_PPC_ISERIES if (firmware_has_feature(FW_FEATURE_ISERIES) && hvlpevent_is_pending()) -- cgit v1.2.3 From 13d7e89ea21d11921cc64729341edb3fbdb70ca9 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 24 Aug 2010 22:54:05 +0200 Subject: p54: fix tx feedback status flag check commit f880c2050f30b23c9b6f80028c09f76e693bf309 upstream. Michael reported that p54* never really entered power save mode, even tough it was enabled. It turned out that upon a power save mode change the firmware will set a special flag onto the last outgoing frame tx status (which in this case is almost always the designated PSM nullfunc frame). This flag confused the driver; It erroneously reported transmission failures to the stack, which then generated the next nullfunc. and so on... Reported-by: Michael Buesch Tested-by: Michael Buesch Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/p54/txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 4e6891099d43..ccb2dd1bf023 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -444,7 +444,7 @@ static void p54_rx_frame_sent(struct p54_common *priv, struct sk_buff *skb) } if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && - (!payload->status)) + !(payload->status & P54_TX_FAILED)) info->flags |= IEEE80211_TX_STAT_ACK; if (payload->status & P54_TX_PSM_CANCELLED) info->flags |= IEEE80211_TX_STAT_TX_FILTERED; -- cgit v1.2.3 From 39fc0591b8b83310bcdf8436bd1f226fc4d6fd23 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 24 Aug 2010 15:27:34 -0400 Subject: ath5k: check return value of ieee80211_get_tx_rate commit d8e1ba76d619dbc0be8fbeee4e6c683b5c812d3a upstream. This avoids a NULL pointer dereference as reported here: https://bugzilla.redhat.com/show_bug.cgi?id=625889 When the WARN condition is hit in ieee80211_get_tx_rate, it will return NULL. So, we need to check the return value and avoid dereferencing it in that case. Signed-off-by: John W. Linville Acked-by: Bob Copeland Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath5k/base.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index ab9fe22e4dc5..f1e3469f92fb 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1318,6 +1318,10 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, PCI_DMA_TODEVICE); rate = ieee80211_get_tx_rate(sc->hw, info); + if (!rate) { + ret = -EINVAL; + goto err_unmap; + } if (info->flags & IEEE80211_TX_CTL_NO_ACK) flags |= AR5K_TXDESC_NOACK; -- cgit v1.2.3 From 53d9dee0d76a860134cb8360f296bb01efea2558 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 30 Aug 2010 12:24:54 +0200 Subject: wireless extensions: fix kernel heap content leak commit 42da2f948d949efd0111309f5827bf0298bcc9a4 upstream. Wireless extensions have an unfortunate, undocumented requirement which requires drivers to always fill iwp->length when returning a successful status. When a driver doesn't do this, it leads to a kernel heap content leak when userspace offers a larger buffer than would have been necessary. Arguably, this is a driver bug, as it should, if it returns 0, fill iwp->length, even if it separately indicated that the buffer contents was not valid. However, we can also at least avoid the memory content leak if the driver doesn't do this by setting the iwp length to max_tokens, which then reflects how big the buffer is that the driver may fill, regardless of how big the userspace buffer is. To illustrate the point, this patch also fixes a corresponding cfg80211 bug (since this requirement isn't documented nor was ever pointed out by anyone during code review, I don't trust all drivers nor all cfg80211 handlers to implement it correctly). Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/wireless/wext-compat.c | 3 +++ net/wireless/wext-core.c | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 96342993cf93..37c7d5b597cc 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -1420,6 +1420,9 @@ int cfg80211_wext_giwessid(struct net_device *dev, { struct wireless_dev *wdev = dev->ieee80211_ptr; + data->flags = 0; + data->length = 0; + switch (wdev->iftype) { case NL80211_IFTYPE_ADHOC: return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 0ef17bc42bac..8f5116f5af19 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -782,6 +782,22 @@ static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd, } } + if (IW_IS_GET(cmd) && !(descr->flags & IW_DESCR_FLAG_NOMAX)) { + /* + * If this is a GET, but not NOMAX, it means that the extra + * data is not bounded by userspace, but by max_tokens. Thus + * set the length to max_tokens. This matches the extra data + * allocation. + * The driver should fill it with the number of tokens it + * provided, and it may check iwp->length rather than having + * knowledge of max_tokens. If the driver doesn't change the + * iwp->length, this ioctl just copies back max_token tokens + * filled with zeroes. Hopefully the driver isn't claiming + * them to be valid data. + */ + iwp->length = descr->max_tokens; + } + err = handler(dev, info, (union iwreq_data *) iwp, extra); iwp->length += essid_compat; -- cgit v1.2.3 From f155ee1b5def75927fd86a839d7ab10b8fa07e79 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Sat, 28 Aug 2010 13:35:05 +0000 Subject: RDMA/cxgb3: Don't exceed the max HW CQ depth commit dc4e96ce2dceb649224ee84f83592aac8c54c9b7 upstream. The max depth supported by T3 is 64K entries. This fixes a bug introduced in commit 9918b28d ("RDMA/cxgb3: Increase the max CQ depth") that causes stalls and possibly crashes in large MPI clusters. Signed-off-by: Steve Wise Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/cxgb3/cxio_hal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.h b/drivers/infiniband/hw/cxgb3/cxio_hal.h index 8f0caf7d4482..78fbe9ffe7f0 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.h +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.h @@ -53,7 +53,7 @@ #define T3_MAX_PBL_SIZE 256 #define T3_MAX_RQ_SIZE 1024 #define T3_MAX_QP_DEPTH (T3_MAX_RQ_SIZE-1) -#define T3_MAX_CQ_DEPTH 262144 +#define T3_MAX_CQ_DEPTH 65536 #define T3_MAX_NUM_STAG (1<<15) #define T3_MAX_MR_SIZE 0x100000000ULL #define T3_PAGESIZE_MASK 0xffff000 /* 4KB-128MB */ -- cgit v1.2.3 From 51fccd339ff9d32702051b240bf2f8fcdd42749b Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 10 Sep 2010 22:32:53 +0200 Subject: x86, tsc: Fix a preemption leak in restore_sched_clock_state() commit 55496c896b8a695140045099d4e0175cf09d4eae upstream. Doh, a real life genuine preemption leak.. This caused a suspend failure. Reported-bisected-and-tested-by-the-invaluable: Jeff Chua Acked-by: Suresh Siddha Signed-off-by: Peter Zijlstra Cc: Rafael J. Wysocki Cc: Nico Schottelius Cc: Jesse Barnes Cc: Linus Torvalds Cc: Florian Pritz Cc: Suresh Siddha Cc: Len Brown sleep states LKML-Reference: <1284150773.402.122.camel@laptop> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/tsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index c65f74152473..4094ae0fac3c 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -655,7 +655,7 @@ void restore_sched_clock_state(void) local_irq_save(flags); - get_cpu_var(cyc2ns_offset) = 0; + __get_cpu_var(cyc2ns_offset) = 0; offset = cyc2ns_suspend - sched_clock(); for_each_possible_cpu(cpu) -- cgit v1.2.3 From 0fd7b7cbc7e04bc859456fbd862dedd6985f85e5 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 14 Sep 2010 12:42:41 -0700 Subject: x86-64, compat: Test %rax for the syscall number, not %eax commit 36d001c70d8a0144ac1d038f6876c484849a74de upstream. On 64 bits, we always, by necessity, jump through the system call table via %rax. For 32-bit system calls, in theory the system call number is stored in %eax, and the code was testing %eax for a valid system call number. At one point we loaded the stored value back from the stack to enforce zero-extension, but that was removed in checkin d4d67150165df8bf1cc05e532f6efca96f907cab. An actual 32-bit process will not be able to introduce a non-zero-extended number, but it can happen via ptrace. Instead of re-introducing the zero-extension, test what we are actually going to use, i.e. %rax. This only adds a handful of REX prefixes to the code. Reported-by: Ben Hawkes Signed-off-by: H. Peter Anvin Cc: Roland McGrath Cc: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- arch/x86/ia32/ia32entry.S | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index e790bc1fbfa3..944e3fc66dce 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -153,7 +153,7 @@ ENTRY(ia32_sysenter_target) testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) CFI_REMEMBER_STATE jnz sysenter_tracesys - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja ia32_badsys sysenter_do_call: IA32_ARG_FIXUP @@ -195,7 +195,7 @@ sysexit_from_sys_call: movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */ call audit_syscall_entry movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */ - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja ia32_badsys movl %ebx,%edi /* reload 1st syscall arg */ movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */ @@ -248,7 +248,7 @@ sysenter_tracesys: call syscall_trace_enter LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */ jmp sysenter_do_call CFI_ENDPROC @@ -314,7 +314,7 @@ ENTRY(ia32_cstar_target) testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) CFI_REMEMBER_STATE jnz cstar_tracesys - cmpl $IA32_NR_syscalls-1,%eax + cmpq $IA32_NR_syscalls-1,%rax ja ia32_badsys cstar_do_call: IA32_ARG_FIXUP 1 @@ -367,7 +367,7 @@ cstar_tracesys: LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */ RESTORE_REST xchgl %ebp,%r9d - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */ jmp cstar_do_call END(ia32_cstar_target) @@ -425,7 +425,7 @@ ENTRY(ia32_syscall) orl $TS_COMPAT,TI_status(%r10) testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) jnz ia32_tracesys - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja ia32_badsys ia32_do_call: IA32_ARG_FIXUP @@ -444,7 +444,7 @@ ia32_tracesys: call syscall_trace_enter LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */ jmp ia32_do_call END(ia32_syscall) -- cgit v1.2.3 From b2e19c77678a5ca5f1233eb7d1989c143386d838 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 7 Sep 2010 16:16:18 -0700 Subject: compat: Make compat_alloc_user_space() incorporate the access_ok() commit c41d68a513c71e35a14f66d71782d27a79a81ea6 upstream. compat_alloc_user_space() expects the caller to independently call access_ok() to verify the returned area. A missing call could introduce problems on some architectures. This patch incorporates the access_ok() check into compat_alloc_user_space() and also adds a sanity check on the length. The existing compat_alloc_user_space() implementations are renamed arch_compat_alloc_user_space() and are used as part of the implementation of the new global function. This patch assumes NULL will cause __get_user()/__put_user() to either fail or access userspace on all architectures. This should be followed by checking the return value of compat_access_user_space() for NULL in the callers, at which time the access_ok() in the callers can also be removed. Reported-by: Ben Hawkes Signed-off-by: H. Peter Anvin Acked-by: Benjamin Herrenschmidt Acked-by: Chris Metcalf Acked-by: David S. Miller Acked-by: Ingo Molnar Acked-by: Thomas Gleixner Acked-by: Tony Luck Cc: Andrew Morton Cc: Arnd Bergmann Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Heiko Carstens Cc: Helge Deller Cc: James Bottomley Cc: Kyle McMartin Cc: Martin Schwidefsky Cc: Paul Mackerras Cc: Ralf Baechle Signed-off-by: Greg Kroah-Hartman --- arch/ia64/include/asm/compat.h | 2 +- arch/mips/include/asm/compat.h | 2 +- arch/parisc/include/asm/compat.h | 2 +- arch/powerpc/include/asm/compat.h | 2 +- arch/s390/include/asm/compat.h | 2 +- arch/sparc/include/asm/compat.h | 2 +- arch/x86/include/asm/compat.h | 2 +- include/linux/compat.h | 3 +++ kernel/compat.c | 21 +++++++++++++++++++++ 9 files changed, 31 insertions(+), 7 deletions(-) diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h index f90edc85b509..9301a2821615 100644 --- a/arch/ia64/include/asm/compat.h +++ b/arch/ia64/include/asm/compat.h @@ -199,7 +199,7 @@ ptr_to_compat(void __user *uptr) } static __inline__ void __user * -compat_alloc_user_space (long len) +arch_compat_alloc_user_space (long len) { struct pt_regs *regs = task_pt_regs(current); return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len); diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h index 613f6912dfc1..dbc51065df5b 100644 --- a/arch/mips/include/asm/compat.h +++ b/arch/mips/include/asm/compat.h @@ -145,7 +145,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) return (u32)(unsigned long)uptr; } -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = (struct pt_regs *) ((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1; diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h index 02b77baa5da6..efa0b60c63fe 100644 --- a/arch/parisc/include/asm/compat.h +++ b/arch/parisc/include/asm/compat.h @@ -147,7 +147,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) return (u32)(unsigned long)uptr; } -static __inline__ void __user *compat_alloc_user_space(long len) +static __inline__ void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = ¤t->thread.regs; return (void __user *)regs->gr[30]; diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index 396d21a80058..a11d4eac4f97 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h @@ -134,7 +134,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) return (u32)(unsigned long)uptr; } -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = current->thread.regs; unsigned long usp = regs->gpr[1]; diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index 104f2007f097..a875c2f542e1 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h @@ -181,7 +181,7 @@ static inline int is_compat_task(void) #endif -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { unsigned long stack; diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index 5016f76ea98a..6f57325bb883 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h @@ -167,7 +167,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) return (u32)(unsigned long)uptr; } -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = current_thread_info()->kregs; unsigned long usp = regs->u_regs[UREG_I6]; diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h index 306160e58b48..1d9cd27c2920 100644 --- a/arch/x86/include/asm/compat.h +++ b/arch/x86/include/asm/compat.h @@ -205,7 +205,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) return (u32)(unsigned long)uptr; } -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = task_pt_regs(current); return (void __user *)regs->sp - len; diff --git a/include/linux/compat.h b/include/linux/compat.h index 168f7daa7bde..c76644178826 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -360,5 +360,8 @@ extern ssize_t compat_rw_copy_check_uvector(int type, const struct compat_iovec __user *uvector, unsigned long nr_segs, unsigned long fast_segs, struct iovec *fast_pointer, struct iovec **ret_pointer); + +extern void __user *compat_alloc_user_space(unsigned long len); + #endif /* CONFIG_COMPAT */ #endif /* _LINUX_COMPAT_H */ diff --git a/kernel/compat.c b/kernel/compat.c index 5adab05a3172..91b33fbcb427 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -1137,3 +1137,24 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info) return 0; } + +/* + * Allocate user-space memory for the duration of a single system call, + * in order to marshall parameters inside a compat thunk. + */ +void __user *compat_alloc_user_space(unsigned long len) +{ + void __user *ptr; + + /* If len would occupy more than half of the entire compat space... */ + if (unlikely(len > (((compat_uptr_t)~0) >> 1))) + return NULL; + + ptr = arch_compat_alloc_user_space(len); + + if (unlikely(!access_ok(VERIFY_WRITE, ptr, len))) + return NULL; + + return ptr; +} +EXPORT_SYMBOL_GPL(compat_alloc_user_space); -- cgit v1.2.3 From 428b01232e08df89751ed5d1683953ebcc6a9035 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 14 Sep 2010 12:22:58 -0700 Subject: x86-64, compat: Retruncate rax after ia32 syscall entry tracing commit eefdca043e8391dcd719711716492063030b55ac upstream. In commit d4d6715, we reopened an old hole for a 64-bit ptracer touching a 32-bit tracee in system call entry. A %rax value set via ptrace at the entry tracing stop gets used whole as a 32-bit syscall number, while we only check the low 32 bits for validity. Fix it by truncating %rax back to 32 bits after syscall_trace_enter, in addition to testing the full 64 bits as has already been added. Reported-by: Ben Hawkes Signed-off-by: Roland McGrath Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/ia32/ia32entry.S | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 944e3fc66dce..4f5f71e03ce1 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -50,7 +50,12 @@ /* * Reload arg registers from stack in case ptrace changed them. * We don't reload %eax because syscall_trace_enter() returned - * the value it wants us to use in the table lookup. + * the %rax value we should see. Instead, we just truncate that + * value to 32 bits again as we did on entry from user mode. + * If it's a new value set by user_regset during entry tracing, + * this matches the normal truncation of the user-mode value. + * If it's -1 to make us punt the syscall, then (u32)-1 is still + * an appropriately invalid value. */ .macro LOAD_ARGS32 offset, _r9=0 .if \_r9 @@ -60,6 +65,7 @@ movl \offset+48(%rsp),%edx movl \offset+56(%rsp),%esi movl \offset+64(%rsp),%edi + movl %eax,%eax /* zero extension */ .endm .macro CFI_STARTPROC32 simple -- cgit v1.2.3 From 1f4536a2af4726c1e27c2fda343d02879eb61e5b Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Thu, 16 Sep 2010 10:07:53 +0200 Subject: ALSA: HDA: Enable internal speaker on Dell M101z commit 145a902bfeb1f89a41165bd2d1e633ce070bcb73 upstream. BugLink: http://launchpad.net/bugs/640254 In some cases a magic processing coefficient is needed to enable the internal speaker on Dell M101z. According to Realtek, this processing coefficient is only present on ALC269vb. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2b9c88990a7b..76c4968c2a38 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -14230,6 +14230,7 @@ static void alc269_auto_init(struct hda_codec *codec) enum { ALC269_FIXUP_SONY_VAIO, + ALC269_FIXUP_DELL_M101Z, }; static const struct hda_verb alc269_sony_vaio_fixup_verbs[] = { @@ -14241,11 +14242,20 @@ static const struct alc_fixup alc269_fixups[] = { [ALC269_FIXUP_SONY_VAIO] = { .verbs = alc269_sony_vaio_fixup_verbs }, + [ALC269_FIXUP_DELL_M101Z] = { + .verbs = (const struct hda_verb[]) { + /* Enables internal speaker */ + {0x20, AC_VERB_SET_COEF_INDEX, 13}, + {0x20, AC_VERB_SET_PROC_COEF, 0x4040}, + {} + } + }, }; static struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), SND_PCI_QUIRK(0x104d, 0x9077, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), + SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), {} }; -- cgit v1.2.3 From e8ba36a90f25685bbdb5a4e4df8a8321ba9f7144 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 14 Sep 2010 22:10:21 +0200 Subject: x86: hpet: Work around hardware stupidity commit 54ff7e595d763d894104d421b103a89f7becf47c upstream. This more or less reverts commits 08be979 (x86: Force HPET readback_cmp for all ATI chipsets) and 30a564be (x86, hpet: Restrict read back to affected ATI chipsets) to the status of commit 8da854c (x86, hpet: Erratum workaround for read after write of HPET comparator). The delta to commit 8da854c is mostly comments and the change from WARN_ONCE to printk_once as we know the call path of this function already. This needs really in depth explanation: First of all the HPET design is a complete failure. Having a counter compare register which generates an interrupt on matching values forces the software to do at least one superfluous readback of the counter register. While it is nice in theory to program "absolute" time events it is practically useless because the timer runs at some absurd frequency which can never be matched to real world units. So we are forced to calculate a relative delta and this forces a readout of the actual counter value, adding the delta and programming the compare register. When the delta is small enough we run into the danger that we program a compare value which is already in the past. Due to the compare for equal nature of HPET we need to read back the counter value after writing the compare rehgister (btw. this is necessary for absolute timeouts as well) to make sure that we did not miss the timer event. We try to work around that by setting the minimum delta to a value which is larger than the theoretical time which elapses between the counter readout and the compare register write, but that's only true in theory. A NMI or SMI which hits between the readout and the write can easily push us beyond that limit. This would result in waiting for the next HPET timer interrupt until the 32bit wraparound of the counter happens which takes about 306 seconds. So we designed the next event function to look like: match = read_cnt() + delta; write_compare_ref(match); return read_cnt() < match ? 0 : -ETIME; At some point we got into trouble with certain ATI chipsets. Even the above "safe" procedure failed. The reason was that the write to the compare register was delayed probably for performance reasons. The theory was that they wanted to avoid the synchronization of the write with the HPET clock, which is understandable. So the write does not hit the compare register directly instead it goes to some intermediate register which is copied to the real compare register in sync with the HPET clock. That opens another window for hitting the dreaded "wait for a wraparound" problem. To work around that "optimization" we added a read back of the compare register which either enforced the update of the just written value or just delayed the readout of the counter enough to avoid the issue. We unfortunately never got any affirmative info from ATI/AMD about this. One thing is sure, that we nuked the performance "optimization" that way completely and I'm pretty sure that the result is worse than before some HW folks came up with those. Just for paranoia reasons I added a check whether the read back compare register value was the same as the value we wrote right before. That paranoia check triggered a couple of years after it was added on an Intel ICH9 chipset. Venki added a workaround (commit 8da854c) which was reading the compare register twice when the first check failed. We considered this to be a penalty in general and restricted the readback (thus the wasted CPU cycles) to the known to be affected ATI chipsets. This turned out to be a utterly wrong decision. 2.6.35 testers experienced massive problems and finally one of them bisected it down to commit 30a564be which spured some further investigation. Finally we got confirmation that the write to the compare register can be delayed by up to two HPET clock cycles which explains the problems nicely. All we can do about this is to go back to Venki's initial workaround in a slightly modified version. Just for the record I need to say, that all of this could have been avoided if hardware designers and of course the HPET committee would have thought about the consequences for a split second. It's out of my comprehension why designing a working timer is so hard. There are two ways to achieve it: 1) Use a counter wrap around aware compare_reg <= counter_reg implementation instead of the easy compare_reg == counter_reg Downsides: - It needs more silicon. - It needs a readout of the counter to apply a relative timeout. This is necessary as the counter does not run in any useful (and adjustable) frequency and there is no guarantee that the counter which is used for timer events is the same which is used for reading the actual time (and therefor for calculating the delta) Upsides: - None 2) Use a simple down counter for relative timer events Downsides: - Absolute timeouts are not possible, which is not a problem at all in the context of an OS and the expected max. latencies/jitter (also see Downsides of #1) Upsides: - It needs less or equal silicon. - It works ALWAYS - It is way faster than a compare register based solution (One write versus one write plus at least one and up to four reads) I would not be so grumpy about all of this, if I would not have been ignored for many years when pointing out these flaws to various hardware folks. I really hate timers (at least those which seem to be designed by janitors). Though finally we got a reasonable explanation plus a solution and I want to thank all the folks involved in chasing it down and providing valuable input to this. Bisected-by: Nix Reported-by: Artur Skawina Reported-by: Damien Wyart Reported-by: John Drescher Cc: Venkatesh Pallipadi Cc: Ingo Molnar Cc: H. Peter Anvin Cc: Arjan van de Ven Cc: Andreas Herrmann Cc: Borislav Petkov Cc: stable@kernel.org Acked-by: Suresh Siddha Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/hpet.h | 1 - arch/x86/kernel/early-quirks.c | 18 ------------------ arch/x86/kernel/hpet.c | 31 +++++++++++++++++-------------- 3 files changed, 17 insertions(+), 33 deletions(-) diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h index 004e6e25e913..1d5c08a1bdfd 100644 --- a/arch/x86/include/asm/hpet.h +++ b/arch/x86/include/asm/hpet.h @@ -68,7 +68,6 @@ extern unsigned long force_hpet_address; extern u8 hpet_blockid; extern int hpet_force_user; extern u8 hpet_msi_disable; -extern u8 hpet_readback_cmp; extern int is_hpet_enabled(void); extern int hpet_enable(void); extern void hpet_disable(void); diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index e5cc7e82e60d..ebdb85cf2686 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -18,7 +18,6 @@ #include #include #include -#include static void __init fix_hypertransport_config(int num, int slot, int func) { @@ -192,21 +191,6 @@ static void __init ati_bugs_contd(int num, int slot, int func) } #endif -/* - * Force the read back of the CMP register in hpet_next_event() - * to work around the problem that the CMP register write seems to be - * delayed. See hpet_next_event() for details. - * - * We do this on all SMBUS incarnations for now until we have more - * information about the affected chipsets. - */ -static void __init ati_hpet_bugs(int num, int slot, int func) -{ -#ifdef CONFIG_HPET_TIMER - hpet_readback_cmp = 1; -#endif -} - #define QFLAG_APPLY_ONCE 0x1 #define QFLAG_APPLIED 0x2 #define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED) @@ -236,8 +220,6 @@ static struct chipset early_qrk[] __initdata = { PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs }, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs_contd }, - { PCI_VENDOR_ID_ATI, PCI_ANY_ID, - PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_hpet_bugs }, {} }; diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index ba390d731175..7cd18862f041 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -36,7 +36,6 @@ unsigned long hpet_address; u8 hpet_blockid; /* OS timer block num */ u8 hpet_msi_disable; -u8 hpet_readback_cmp; #ifdef CONFIG_PCI_MSI static unsigned long hpet_num_timers; @@ -396,23 +395,27 @@ static int hpet_next_event(unsigned long delta, * at that point and we would wait for the next hpet interrupt * forever. We found out that reading the CMP register back * forces the transfer so we can rely on the comparison with - * the counter register below. + * the counter register below. If the read back from the + * compare register does not match the value we programmed + * then we might have a real hardware problem. We can not do + * much about it here, but at least alert the user/admin with + * a prominent warning. * - * That works fine on those ATI chipsets, but on newer Intel - * chipsets (ICH9...) this triggers due to an erratum: Reading - * the comparator immediately following a write is returning - * the old value. + * An erratum on some chipsets (ICH9,..), results in + * comparator read immediately following a write returning old + * value. Workaround for this is to read this value second + * time, when first read returns old value. * - * We restrict the read back to the affected ATI chipsets (set - * by quirks) and also run it with hpet=verbose for debugging - * purposes. + * In fact the write to the comparator register is delayed up + * to two HPET cycles so the workaround we tried to restrict + * the readback to those known to be borked ATI chipsets + * failed miserably. So we give up on optimizations forever + * and penalize all HPET incarnations unconditionally. */ - if (hpet_readback_cmp || hpet_verbose) { - u32 cmp = hpet_readl(HPET_Tn_CMP(timer)); - - if (cmp != cnt) + if (unlikely((u32)hpet_readl(HPET_Tn_CMP(timer)) != cnt)) { + if (hpet_readl(HPET_Tn_CMP(timer)) != cnt) printk_once(KERN_WARNING - "hpet: compare register read back failed.\n"); + "hpet: compare register read back failed.\n"); } return (s32)(hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0; -- cgit v1.2.3 From 9f6ea8d2fd0d4cb9939aae51a6522600f93161f6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Sep 2010 14:34:39 +0100 Subject: arm: fix really nasty sigreturn bug commit 653d48b22166db2d8b1515ebe6f9f0f7c95dfc86 upstream. If a signal hits us outside of a syscall and another gets delivered when we are in sigreturn (e.g. because it had been in sa_mask for the first one and got sent to us while we'd been in the first handler), we have a chance of returning from the second handler to location one insn prior to where we ought to return. If r0 happens to contain -513 (-ERESTARTNOINTR), sigreturn will get confused into doing restart syscall song and dance. Incredible joy to debug, since it manifests as random, infrequent and very hard to reproduce double execution of instructions in userland code... The fix is simple - mark it "don't bother with restarts" in wrapper, i.e. set r8 to 0 in sys_sigreturn and sys_rt_sigreturn wrappers, suppressing the syscall restart handling on return from these guys. They can't legitimately return a restart-worthy error anyway. Testcase: #include #include #include #include #include void f(int n) { __asm__ __volatile__( "ldr r0, [%0]\n" "b 1f\n" "b 2f\n" "1:b .\n" "2:\n" : : "r"(&n)); } void handler1(int sig) { } void handler2(int sig) { raise(1); } void handler3(int sig) { exit(0); } main() { struct sigaction s = {.sa_handler = handler2}; struct itimerval t1 = { .it_value = {1} }; struct itimerval t2 = { .it_value = {2} }; signal(1, handler1); sigemptyset(&s.sa_mask); sigaddset(&s.sa_mask, 1); sigaction(SIGALRM, &s, NULL); signal(SIGVTALRM, handler3); setitimer(ITIMER_REAL, &t1, NULL); setitimer(ITIMER_VIRTUAL, &t2, NULL); f(-513); /* -ERESTARTNOINTR */ write(1, "buggered\n", 9); return 1; } Signed-off-by: Al Viro Acked-by: Russell King Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/entry-common.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 2c1db77d7848..a6c66f598d14 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -382,11 +382,13 @@ ENDPROC(sys_clone_wrapper) sys_sigreturn_wrapper: add r0, sp, #S_OFF + mov why, #0 @ prevent syscall restart handling b sys_sigreturn ENDPROC(sys_sigreturn_wrapper) sys_rt_sigreturn_wrapper: add r0, sp, #S_OFF + mov why, #0 @ prevent syscall restart handling b sys_rt_sigreturn ENDPROC(sys_rt_sigreturn_wrapper) -- cgit v1.2.3 From dd32c724fe62ccb8675f703481694a5ac5ebfa0d Mon Sep 17 00:00:00 2001 From: Yong Wang Date: Fri, 17 Sep 2010 17:24:12 +0200 Subject: hwmon: (emc1403) Remove unnecessary hwmon_device_unregister commit f17c811d1433aa1966f9c5a744841427e9a97ecf upstream. It is unnecessary and wrong to call hwmon_device_unregister in error handling before hwmon_device_register is called. Signed-off-by: Yong Wang Reviewed-by: Guenter Roeck Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/emc1403.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index 0e4b5642638d..3f5a00e51615 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c @@ -275,7 +275,6 @@ static int emc1403_probe(struct i2c_client *client, res = sysfs_create_group(&client->dev.kobj, &m_thermal_gr); if (res) { dev_warn(&client->dev, "create group failed\n"); - hwmon_device_unregister(data->hwmon_dev); goto thermal_error1; } data->hwmon_dev = hwmon_device_register(&client->dev); -- cgit v1.2.3 From 75455a5495aff05dfae801e29764ce65cd59862a Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Fri, 17 Sep 2010 17:24:11 +0200 Subject: hwmon: (f75375s) Shift control mode to the correct bit position commit 96f3640894012be7dd15a384566bfdc18297bc6c upstream. The spec notes that fan0 and fan1 control mode bits are located in bits 7-6 and 5-4 respectively, but the FAN_CTRL_MODE macro was making the bits shift by 5 instead of by 4. Signed-off-by: Guillem Jover Cc: Riku Voipio Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/f75375s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 0f58ecc5334d..e5828c009d91 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -79,7 +79,7 @@ enum chips { f75373, f75375 }; #define F75375_REG_PWM2_DROP_DUTY 0x6C #define FAN_CTRL_LINEAR(nr) (4 + nr) -#define FAN_CTRL_MODE(nr) (5 + ((nr) * 2)) +#define FAN_CTRL_MODE(nr) (4 + ((nr) * 2)) /* * Data structures and manipulation thereof -- cgit v1.2.3 From 12c5db341875a05f9986a3f18d008f0f423ec390 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Fri, 17 Sep 2010 17:24:12 +0200 Subject: hwmon: (f75375s) Do not overwrite values read from registers commit c3b327d60bbba3f5ff8fd87d1efc0e95eb6c121b upstream. All bits in the values read from registers to be used for the next write were getting overwritten, avoid doing so to not mess with the current configuration. Signed-off-by: Guillem Jover Cc: Riku Voipio Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/f75375s.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index e5828c009d91..9638d58f99fd 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -298,7 +298,7 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val) return -EINVAL; fanmode = f75375_read8(client, F75375_REG_FAN_TIMER); - fanmode = ~(3 << FAN_CTRL_MODE(nr)); + fanmode &= ~(3 << FAN_CTRL_MODE(nr)); switch (val) { case 0: /* Full speed */ @@ -350,7 +350,7 @@ static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); conf = f75375_read8(client, F75375_REG_CONFIG1); - conf = ~(1 << FAN_CTRL_LINEAR(nr)); + conf &= ~(1 << FAN_CTRL_LINEAR(nr)); if (val == 0) conf |= (1 << FAN_CTRL_LINEAR(nr)) ; -- cgit v1.2.3 From 1a5029d51d4a82c05596b317be20a2c660f68853 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Wed, 8 Sep 2010 00:10:26 +0400 Subject: apm_power: Add missing break statement commit 1d220334d6a8a711149234dc5f98d34ae02226b8 upstream. The missing break statement causes wrong capacity calculation for batteries that report energy. Reported-by: d binderman Signed-off-by: Anton Vorontsov Signed-off-by: Greg Kroah-Hartman --- drivers/power/apm_power.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c index 936bae560fa1..dc628cb2e762 100644 --- a/drivers/power/apm_power.c +++ b/drivers/power/apm_power.c @@ -233,6 +233,7 @@ static int calculate_capacity(enum apm_source source) empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN; now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; + break; case SOURCE_VOLTAGE: full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX; empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN; -- cgit v1.2.3 From 801c1aca52fb016a47c77c8e61df5e2f6da5c406 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 14 Sep 2010 11:38:24 -0400 Subject: cifs: fix potential double put of TCP session reference commit 460cf3411b858ad509d5255e0dfaf862a83c0299 upstream. cifs_get_smb_ses must be called on a server pointer on which it holds an active reference. It first does a search for an existing SMB session. If it finds one, it'll put the server reference and then try to ensure that the negprot is done, etc. If it encounters an error at that point then it'll return an error. There's a potential problem here though. When cifs_get_smb_ses returns an error, the caller will also put the TCP server reference leading to a double-put. Fix this by having cifs_get_smb_ses only put the server reference if it found an existing session that it could use and isn't returning an error. Reviewed-by: Suresh Jayaraman Signed-off-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/connect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 2208f06e4c45..fa1039a7ac40 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1647,9 +1647,6 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) if (ses) { cFYI(1, "Existing smb sess found (status=%d)", ses->status); - /* existing SMB ses has a server reference already */ - cifs_put_tcp_session(server); - mutex_lock(&ses->session_mutex); rc = cifs_negotiate_protocol(xid, ses); if (rc) { @@ -1672,6 +1669,9 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) } } mutex_unlock(&ses->session_mutex); + + /* existing SMB ses has a server reference already */ + cifs_put_tcp_session(server); FreeXid(xid); return ses; } -- cgit v1.2.3 From 5c41628055bec9f45fe29c8b553c6048c053236c Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sun, 12 Sep 2010 19:55:26 -0400 Subject: NFS: Fix a typo in nfs_sockaddr_match_ipaddr6 commit b20d37ca9561711c6a3c4b859c2855f49565e061 upstream. Reported-by: Ben Greear Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index d25b5257b7a1..e0067708a553 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -274,7 +274,7 @@ static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, sin1->sin6_scope_id != sin2->sin6_scope_id) return 0; - return ipv6_addr_equal(&sin1->sin6_addr, &sin1->sin6_addr); + return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr); } #else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */ static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, -- cgit v1.2.3 From 661b2c51d9f019662ce1584d6def2fe2f05096da Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sun, 12 Sep 2010 19:55:25 -0400 Subject: SUNRPC: Fix race corrupting rpc upcall commit 5a67657a2e90c9e4a48518f95d4ba7777aa20fbb upstream. If rpc_queue_upcall() adds a new upcall to the rpci->pipe list just after rpc_pipe_release calls rpc_purge_list(), but before it calls gss_pipe_release (as rpci->ops->release_pipe(inode)), then the latter will free a message without deleting it from the rpci->pipe list. We will be left with a freed object on the rpc->pipe list. Most frequent symptoms are kernel crashes in rpc.gssd system calls on the pipe in question. Reported-by: J. Bruce Fields Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/auth_gss/auth_gss.c | 9 +++++---- net/sunrpc/rpc_pipe.c | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 8da2a0e68574..5359f36f6b41 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -745,17 +745,18 @@ gss_pipe_release(struct inode *inode) struct rpc_inode *rpci = RPC_I(inode); struct gss_upcall_msg *gss_msg; +restart: spin_lock(&inode->i_lock); - while (!list_empty(&rpci->in_downcall)) { + list_for_each_entry(gss_msg, &rpci->in_downcall, list) { - gss_msg = list_entry(rpci->in_downcall.next, - struct gss_upcall_msg, list); + if (!list_empty(&gss_msg->msg.list)) + continue; gss_msg->msg.errno = -EPIPE; atomic_inc(&gss_msg->count); __gss_unhash_msg(gss_msg); spin_unlock(&inode->i_lock); gss_release_msg(gss_msg); - spin_lock(&inode->i_lock); + goto restart; } spin_unlock(&inode->i_lock); diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 95ccbcf45d3e..41a762f82630 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -48,7 +48,7 @@ static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, return; do { msg = list_entry(head->next, struct rpc_pipe_msg, list); - list_del(&msg->list); + list_del_init(&msg->list); msg->errno = err; destroy_msg(msg); } while (!list_empty(head)); @@ -208,7 +208,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp) if (msg != NULL) { spin_lock(&inode->i_lock); msg->errno = -EAGAIN; - list_del(&msg->list); + list_del_init(&msg->list); spin_unlock(&inode->i_lock); rpci->ops->destroy_msg(msg); } @@ -268,7 +268,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) if (res < 0 || msg->len == msg->copied) { filp->private_data = NULL; spin_lock(&inode->i_lock); - list_del(&msg->list); + list_del_init(&msg->list); spin_unlock(&inode->i_lock); rpci->ops->destroy_msg(msg); } -- cgit v1.2.3 From 0b6945bff05e0426960c5db1f5b94f7627d0fe62 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 4 Sep 2010 14:57:27 +0100 Subject: agp/intel: Promote warning about failure to setup flush to error. commit df51e7aa2cf204e3a65657a1d60b96cfda133e9b upstream. Make sure we always detect when we fail to correctly allocate the Isoch Flush Page and print an error to warn the user about the likely memory corruption that will result in invalid rendering or worse. Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/char/agp/intel-gtt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index d84af6c9370e..ea6997e3558e 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1061,11 +1061,11 @@ static void intel_i9xx_setup_flush(void) intel_i915_setup_chipset_flush(); } - if (intel_private.ifp_resource.start) { + if (intel_private.ifp_resource.start) intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); - if (!intel_private.i9xx_flush_page) - dev_info(&intel_private.pcidev->dev, "can't ioremap flush page - no chipset flushing"); - } + if (!intel_private.i9xx_flush_page) + dev_err(&intel_private.pcidev->dev, + "can't ioremap flush page - no chipset flushing\n"); } static int intel_i9xx_configure(void) -- cgit v1.2.3 From 0e4112f04521bddfd3ce4598076bb0c557b259c6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Aug 2010 13:59:54 -0400 Subject: drm/radeon/kms: fix a regression on r7xx AGP due to the HDP flush fix commit 87cbf8f2c5d1b1fc4642c3dc0bb6efc587479603 upstream. commit: 812d046915f48236657f02c06d7dc47140e9ceda drm/radeon/kms/r7xx: add workaround for hw issue with HDP flush breaks on AGP boards since there is no VRAM gart table. This patch fixes the issue by creating a VRAM scratch page so that can be used on both AGP and PCIE. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=29834 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/r600.c | 2 +- drivers/gpu/drm/radeon/radeon.h | 6 +++++ drivers/gpu/drm/radeon/rv770.c | 52 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index bb3de0158460..a267259fb260 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3526,7 +3526,7 @@ void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo) * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL */ if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) { - void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; + void __iomem *ptr = (void *)rdev->vram_scratch.ptr; u32 tmp; WREG32(HDP_DEBUG1, 0); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 2f94dc66c183..e0865c7d813c 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -997,6 +997,11 @@ int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); +/* VRAM scratch page for HDP bug */ +struct r700_vram_scratch { + struct radeon_bo *robj; + volatile uint32_t *ptr; +}; /* * Core structure, functions and helpers. @@ -1060,6 +1065,7 @@ struct radeon_device { const struct firmware *pfp_fw; /* r6/700 PFP firmware */ const struct firmware *rlc_fw; /* r6/700 RLC firmware */ struct r600_blit r600_blit; + struct r700_vram_scratch vram_scratch; int msi_enabled; /* msi enabled */ struct r600_ih ih; /* r6/700 interrupt ring */ struct workqueue_struct *wq; diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 1d6fb79de27e..67e807371a08 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -889,6 +889,54 @@ static void rv770_gpu_init(struct radeon_device *rdev) } +static int rv770_vram_scratch_init(struct radeon_device *rdev) +{ + int r; + u64 gpu_addr; + + if (rdev->vram_scratch.robj == NULL) { + r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, + true, RADEON_GEM_DOMAIN_VRAM, + &rdev->vram_scratch.robj); + if (r) { + return r; + } + } + + r = radeon_bo_reserve(rdev->vram_scratch.robj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rdev->vram_scratch.robj, + RADEON_GEM_DOMAIN_VRAM, &gpu_addr); + if (r) { + radeon_bo_unreserve(rdev->vram_scratch.robj); + return r; + } + r = radeon_bo_kmap(rdev->vram_scratch.robj, + (void **)&rdev->vram_scratch.ptr); + if (r) + radeon_bo_unpin(rdev->vram_scratch.robj); + radeon_bo_unreserve(rdev->vram_scratch.robj); + + return r; +} + +static void rv770_vram_scratch_fini(struct radeon_device *rdev) +{ + int r; + + if (rdev->vram_scratch.robj == NULL) { + return; + } + r = radeon_bo_reserve(rdev->vram_scratch.robj, false); + if (likely(r == 0)) { + radeon_bo_kunmap(rdev->vram_scratch.robj); + radeon_bo_unpin(rdev->vram_scratch.robj); + radeon_bo_unreserve(rdev->vram_scratch.robj); + } + radeon_bo_unref(&rdev->vram_scratch.robj); +} + int rv770_mc_init(struct radeon_device *rdev) { u32 tmp; @@ -954,6 +1002,9 @@ static int rv770_startup(struct radeon_device *rdev) if (r) return r; } + r = rv770_vram_scratch_init(rdev); + if (r) + return r; rv770_gpu_init(rdev); r = r600_blit_init(rdev); if (r) { @@ -1179,6 +1230,7 @@ void rv770_fini(struct radeon_device *rdev) r600_irq_fini(rdev); radeon_irq_kms_fini(rdev); rv770_pcie_gart_fini(rdev); + rv770_vram_scratch_fini(rdev); radeon_gem_fini(rdev); radeon_fence_driver_fini(rdev); radeon_clocks_fini(rdev); -- cgit v1.2.3 From b04d80baa88f163b0793318ee4423097f47c59c7 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 30 Aug 2010 16:12:42 +0800 Subject: drm/i915: Enable MI_FLUSH on Sandybridge commit a69ffdbfcba8eabf2ca9d384b578e6f28b339c61 upstream. MI_FLUSH is being deprecated, but still available on Sandybridge. Make sure it's enabled as userspace still uses MI_FLUSH. Signed-off-by: Zhenyu Wang Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_ringbuffer.c | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index cf41c672defe..f9e17b10949c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -312,6 +312,7 @@ #define MI_MODE 0x0209c # define VS_TIMER_DISPATCH (1 << 6) +# define MI_FLUSH_ENABLE (1 << 11) #define SCPD0 0x0209c /* 915+ only */ #define IER 0x020a0 diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 26362f8495a8..4d9c5ce5a123 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -203,9 +203,13 @@ static int init_render_ring(struct drm_device *dev, { drm_i915_private_t *dev_priv = dev->dev_private; int ret = init_ring_common(dev, ring); + int mode; + if (IS_I9XX(dev) && !IS_GEN3(dev)) { - I915_WRITE(MI_MODE, - (VS_TIMER_DISPATCH) << 16 | VS_TIMER_DISPATCH); + mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH; + if (IS_GEN6(dev)) + mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE; + I915_WRITE(MI_MODE, mode); } return ret; } -- cgit v1.2.3 From 8fa162939f360898dfefde73219b1a2682051b01 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 1 Sep 2010 12:03:37 -0400 Subject: drm/radeon/kms: force legacy pll algo for RV515 LVDS commit 0d9958b18e10d7426d94cc3dd024920a40db3ee2 upstream. There has been periodic evidence that LVDS, on at least some panels, prefers the dividers selected by the legacy pll algo. This patch forces the use of the legacy pll algo on RV515 LVDS panels. The old behavior (new pll algo) can be selected by setting the new_pll module parameter to 1. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_crtc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 8c2d6478a221..3271b5a3421f 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -527,6 +527,20 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, pll->algo = PLL_ALGO_LEGACY; pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; } + /* There is some evidence (often anecdotal) that RV515 LVDS + * (on some boards at least) prefers the legacy algo. I'm not + * sure whether this should handled generically or on a + * case-by-case quirk basis. Both algos should work fine in the + * majority of cases. + */ + if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) && + (rdev->family == CHIP_RV515)) { + /* allow the user to overrride just in case */ + if (radeon_new_pll == 1) + pll->algo = PLL_ALGO_NEW; + else + pll->algo = PLL_ALGO_LEGACY; + } } else { if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; -- cgit v1.2.3 From af38a70db3311742ab23f02bc17cd7400bd6202a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 7 Sep 2010 11:42:45 -0400 Subject: drm/radeon/kms: force legacy pll algo for RV620 LVDS commit f90087eea44ce5fad139f086bc9d89ca37b0edc2 upstream. There has been periodic evidence that LVDS, on at least some panels, prefers the dividers selected by the legacy pll algo. This patch forces the use of the legacy pll algo on RV620 LVDS panels. The old behavior (new pll algo) can be selected by setting the new_pll module parameter to 1. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=30029 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_crtc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 3271b5a3421f..eac868a6cd11 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -527,14 +527,15 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, pll->algo = PLL_ALGO_LEGACY; pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; } - /* There is some evidence (often anecdotal) that RV515 LVDS + /* There is some evidence (often anecdotal) that RV515/RV620 LVDS * (on some boards at least) prefers the legacy algo. I'm not * sure whether this should handled generically or on a * case-by-case quirk basis. Both algos should work fine in the * majority of cases. */ if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) && - (rdev->family == CHIP_RV515)) { + ((rdev->family == CHIP_RV515) || + (rdev->family == CHIP_RV620))) { /* allow the user to overrride just in case */ if (radeon_new_pll == 1) pll->algo = PLL_ALGO_NEW; -- cgit v1.2.3 From 314a41c56b32278dcce158a35cabfde3f9e4dcd1 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 1 Sep 2010 17:20:42 -0400 Subject: drm/radeon/kms: properly set crtc high base on r7xx commit 95347871865ca5093c7e87a223274f7c3b5eccda upstream. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_crtc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index eac868a6cd11..1d67f4de7f1a 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1007,11 +1007,11 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, if (rdev->family >= CHIP_RV770) { if (radeon_crtc->crtc_id) { - WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0); - WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0); + WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); + WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); } else { - WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0); - WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0); + WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); + WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); } } WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, -- cgit v1.2.3 From 262a57c09e0c11f9ba2343664998585ece06104e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 2 Sep 2010 21:32:32 -0400 Subject: drm/radeon/kms/evergreen: fix gpu hangs in userspace accel code commit 7e7b41d2ff30ed7ad4bf401d18566e6f38e42e4f upstream. These VGT regs need to be programmed via the ring rather than MMIO as on previous asics (r6xx/r7xx). Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen.c | 39 +++++++++++++++++++++++++++++++++++++- drivers/gpu/drm/radeon/r600.c | 5 +---- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 1caf625e472b..0f077fa06f37 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -658,6 +658,43 @@ static int evergreen_cp_load_microcode(struct radeon_device *rdev) return 0; } +static int evergreen_cp_start(struct radeon_device *rdev) +{ + int r; + uint32_t cp_me; + + r = radeon_ring_lock(rdev, 7); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } + radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5)); + radeon_ring_write(rdev, 0x1); + radeon_ring_write(rdev, 0x0); + radeon_ring_write(rdev, rdev->config.evergreen.max_hw_contexts - 1); + radeon_ring_write(rdev, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); + radeon_ring_write(rdev, 0); + radeon_ring_write(rdev, 0); + radeon_ring_unlock_commit(rdev); + + cp_me = 0xff; + WREG32(CP_ME_CNTL, cp_me); + + r = radeon_ring_lock(rdev, 4); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } + /* init some VGT regs */ + radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); + radeon_ring_write(rdev, (VGT_VERTEX_REUSE_BLOCK_CNTL - PACKET3_SET_CONTEXT_REG_START) >> 2); + radeon_ring_write(rdev, 0xe); + radeon_ring_write(rdev, 0x10); + radeon_ring_unlock_commit(rdev); + + return 0; +} + int evergreen_cp_resume(struct radeon_device *rdev) { u32 tmp; @@ -702,7 +739,7 @@ int evergreen_cp_resume(struct radeon_device *rdev) rdev->cp.rptr = RREG32(CP_RB_RPTR); rdev->cp.wptr = RREG32(CP_RB_WPTR); - r600_cp_start(rdev); + evergreen_cp_start(rdev); rdev->cp.ready = true; r = radeon_ring_test(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index a267259fb260..952cc780230f 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2104,10 +2104,7 @@ int r600_cp_start(struct radeon_device *rdev) } radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5)); radeon_ring_write(rdev, 0x1); - if (rdev->family >= CHIP_CEDAR) { - radeon_ring_write(rdev, 0x0); - radeon_ring_write(rdev, rdev->config.evergreen.max_hw_contexts - 1); - } else if (rdev->family >= CHIP_RV770) { + if (rdev->family >= CHIP_RV770) { radeon_ring_write(rdev, 0x0); radeon_ring_write(rdev, rdev->config.rv770.max_hw_contexts - 1); } else { -- cgit v1.2.3 From 6a32943a76ec1489c497c8f1671080043686f31f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 9 Sep 2010 19:15:23 -0400 Subject: drm/radeon/kms/evergreen: fix backend setup commit b741be82cf2079f71553af595610f17a3a3a752a upstream. This patch fixes rendering errors on some evergreen boards. Hardcoding the backend map is not an optimal solution, but a better fix is being worked on. Similar to the fix for rv740 (6271901d828b34b27607314026deaf417f9f9b75). Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=29986 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 0f077fa06f37..d448c25d25c8 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1143,14 +1143,25 @@ static void evergreen_gpu_init(struct radeon_device *rdev) EVERGREEN_MAX_BACKENDS_MASK)); break; } - } else - gb_backend_map = - evergreen_get_tile_pipe_to_backend_map(rdev, - rdev->config.evergreen.max_tile_pipes, - rdev->config.evergreen.max_backends, - ((EVERGREEN_MAX_BACKENDS_MASK << - rdev->config.evergreen.max_backends) & - EVERGREEN_MAX_BACKENDS_MASK)); + } else { + switch (rdev->family) { + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + gb_backend_map = 0x66442200; + break; + case CHIP_JUNIPER: + gb_backend_map = 0x00006420; + break; + default: + gb_backend_map = + evergreen_get_tile_pipe_to_backend_map(rdev, + rdev->config.evergreen.max_tile_pipes, + rdev->config.evergreen.max_backends, + ((EVERGREEN_MAX_BACKENDS_MASK << + rdev->config.evergreen.max_backends) & + EVERGREEN_MAX_BACKENDS_MASK)); + } + } WREG32(GB_BACKEND_MAP, gb_backend_map); WREG32(GB_ADDR_CONFIG, gb_addr_config); -- cgit v1.2.3 From 8ea422ed02643c645c75cbf29921fdcc8638bc99 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 19 Jun 2010 15:12:51 +0200 Subject: i915: return -EFAULT if copy_to_user fails commit 9927a403ca8c97798129953fa9cbb5dc259c7cb9 upstream. copy_to_user returns the number of bytes remaining to be copied, but we want to return a negative error code here. These are returned to userspace. Signed-off-by: Dan Carpenter Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_dma.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 013a0aeff709..28efc2d16fed 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -612,8 +612,10 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, ret = copy_from_user(cliprects, batch->cliprects, batch->num_cliprects * sizeof(struct drm_clip_rect)); - if (ret != 0) + if (ret != 0) { + ret = -EFAULT; goto fail_free; + } } mutex_lock(&dev->struct_mutex); @@ -654,8 +656,10 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, return -ENOMEM; ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz); - if (ret != 0) + if (ret != 0) { + ret = -EFAULT; goto fail_batch_free; + } if (cmdbuf->num_cliprects) { cliprects = kcalloc(cmdbuf->num_cliprects, @@ -668,8 +672,10 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, ret = copy_from_user(cliprects, cmdbuf->cliprects, cmdbuf->num_cliprects * sizeof(struct drm_clip_rect)); - if (ret != 0) + if (ret != 0) { + ret = -EFAULT; goto fail_clip_free; + } } mutex_lock(&dev->struct_mutex); -- cgit v1.2.3 From 9ee313881759bde1d4bd812dda4fb53d856be4a2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 23 Jun 2010 19:03:01 +0200 Subject: i915_gem: return -EFAULT if copy_to_user fails commit c877cdce93a44eea96f6cf7fc04be7d0372db2be upstream. copy_to_user() returns the number of bytes remaining to be copied and I'm pretty sure we want to return a negative error code here. Signed-off-by: Dan Carpenter Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_gem.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 5aa747fc25a9..06f82382ce6d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3709,6 +3709,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, if (ret != 0) { DRM_ERROR("copy %d cliprects failed: %d\n", args->num_cliprects, ret); + ret = -EFAULT; goto pre_mutex_err; } } -- cgit v1.2.3 From 1c6fd63ca08484ee60853bd17ba18dd24bd21616 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 18 Aug 2010 18:12:56 +0100 Subject: drm/i915/dp: Really try 5 times before giving up. commit 4f7f7b7eb94bd37c449f06932459bbed78826f8d upstream. Only stop trying if the aux channel sucessfully reports that the transmission was completed, otherwise try again. On the 5th failure, bail and report that something is amiss. This fixes a sporadic failure in reading the EDID for my external panel over DP. Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_dp.c | 58 ++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5dde80f9e652..d9de8f12230d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -229,7 +229,6 @@ intel_dp_aux_ch(struct intel_encoder *intel_encoder, uint32_t ch_data = ch_ctl + 4; int i; int recv_bytes; - uint32_t ctl; uint32_t status; uint32_t aux_clock_divider; int try, precharge; @@ -253,41 +252,43 @@ intel_dp_aux_ch(struct intel_encoder *intel_encoder, else precharge = 5; + if (I915_READ(ch_ctl) & DP_AUX_CH_CTL_SEND_BUSY) { + DRM_ERROR("dp_aux_ch not started status 0x%08x\n", + I915_READ(ch_ctl)); + return -EBUSY; + } + /* Must try at least 3 times according to DP spec */ for (try = 0; try < 5; try++) { /* Load the send data into the aux channel data registers */ - for (i = 0; i < send_bytes; i += 4) { - uint32_t d = pack_aux(send + i, send_bytes - i); - - I915_WRITE(ch_data + i, d); - } - - ctl = (DP_AUX_CH_CTL_SEND_BUSY | - DP_AUX_CH_CTL_TIME_OUT_400us | - (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | - (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | - (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | - DP_AUX_CH_CTL_DONE | - DP_AUX_CH_CTL_TIME_OUT_ERROR | - DP_AUX_CH_CTL_RECEIVE_ERROR); + for (i = 0; i < send_bytes; i += 4) + I915_WRITE(ch_data + i, + pack_aux(send + i, send_bytes - i)); /* Send the command and wait for it to complete */ - I915_WRITE(ch_ctl, ctl); - (void) I915_READ(ch_ctl); + I915_WRITE(ch_ctl, + DP_AUX_CH_CTL_SEND_BUSY | + DP_AUX_CH_CTL_TIME_OUT_400us | + (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | + (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | + (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | + DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR); for (;;) { - udelay(100); status = I915_READ(ch_ctl); if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) break; + udelay(100); } /* Clear done status and any errors */ - I915_WRITE(ch_ctl, (status | - DP_AUX_CH_CTL_DONE | - DP_AUX_CH_CTL_TIME_OUT_ERROR | - DP_AUX_CH_CTL_RECEIVE_ERROR)); - (void) I915_READ(ch_ctl); - if ((status & DP_AUX_CH_CTL_TIME_OUT_ERROR) == 0) + I915_WRITE(ch_ctl, + status | + DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR); + if (status & DP_AUX_CH_CTL_DONE) break; } @@ -314,15 +315,12 @@ intel_dp_aux_ch(struct intel_encoder *intel_encoder, /* Unload any bytes sent back from the other side */ recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); - if (recv_bytes > recv_size) recv_bytes = recv_size; - for (i = 0; i < recv_bytes; i += 4) { - uint32_t d = I915_READ(ch_data + i); - - unpack_aux(d, recv + i, recv_bytes - i); - } + for (i = 0; i < recv_bytes; i += 4) + unpack_aux(I915_READ(ch_data + i), + recv + i, recv_bytes - i); return recv_bytes; } -- cgit v1.2.3 From 3eef1e7f9a6569add20ce16afdf52aca42661997 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 20 Aug 2010 14:36:45 +0100 Subject: drm/i915: Allocate the PCI resource for the MCHBAR commit a25c25c2a2aa55e609099a9f74453c518aec29a6 upstream. We were failing when trying to allocate the resource for MMIO of the MCHBAR because we forgot to specify what type of resource we wanted. Signed-off-by: Chris Wilson Cc: Jesse Barnes Reviewed-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_dma.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 28efc2d16fed..5786737ef048 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -883,7 +883,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev) int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915; u32 temp_lo, temp_hi = 0; u64 mchbar_addr; - int ret = 0; + int ret; if (IS_I965G(dev)) pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi); @@ -893,22 +893,23 @@ intel_alloc_mchbar_resource(struct drm_device *dev) /* If ACPI doesn't have it, assume we need to allocate it ourselves */ #ifdef CONFIG_PNP if (mchbar_addr && - pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) { - ret = 0; - goto out; - } + pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) + return 0; #endif /* Get some space for it */ - ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, &dev_priv->mch_res, + dev_priv->mch_res.name = "i915 MCHBAR"; + dev_priv->mch_res.flags = IORESOURCE_MEM; + ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, + &dev_priv->mch_res, MCHBAR_SIZE, MCHBAR_SIZE, PCIBIOS_MIN_MEM, - 0, pcibios_align_resource, + 0, pcibios_align_resource, dev_priv->bridge_dev); if (ret) { DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret); dev_priv->mch_res.start = 0; - goto out; + return ret; } if (IS_I965G(dev)) @@ -917,8 +918,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev) pci_write_config_dword(dev_priv->bridge_dev, reg, lower_32_bits(dev_priv->mch_res.start)); -out: - return ret; + return 0; } /* Setup MCHBAR if possible, return true if we should disable it again */ -- cgit v1.2.3 From d3899a1634c427dbc7c43a6133b126a58c66a934 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 30 Aug 2010 21:25:23 +0200 Subject: drm/i915: overlay on gen2 can't address above 1G commit 9f82d23846146990d475f6753be733e55788d88d upstream. So set the coherent dma mask accordingly. This dma mask is only used for physical objects, so it won't really matter allocation-wise. Now this never really surfaced because sane 32bit kernels only have 1G of lowmem. But some eager testers (distros?) still carry around the patch to adjust lowmem via a kconfig option. And the kernel seems to favour high allocations on boot-up, hence the overlay blowing up reliably. Because the patch is tiny and nicely shows how broken gen2 is it's imho worth to merge despite the fact that mucking around with the lowmem/ highmem division is (no longer) supported. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=28318 Signed-off-by: Daniel Vetter Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_dma.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 5786737ef048..ce8ff0e55152 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -2079,6 +2079,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto free_priv; } + /* overlay on gen2 is broken and can't address above 1G */ + if (IS_GEN2(dev)) + dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(30)); + dev_priv->regs = ioremap(base, size); if (!dev_priv->regs) { DRM_ERROR("failed to map registers\n"); -- cgit v1.2.3 From 2a0726e890af8f37f039cbec69b7c4f422e5ddf7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 6 Sep 2010 16:17:22 +0100 Subject: drm/i915: Prevent double dpms on commit 032d2a0d068b0368296a56469761394ef03207c3 upstream. Arguably this is a bug in drm-core in that we should not be called twice in succession with DPMS_ON, however this is still occuring and we see FDI link training failures on the second call leading to the occassional blank display. For the time being ignore the repeated call. Original patch by Dave Airlie Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e9a4b125d66e..18f317f1dd01 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2314,6 +2314,9 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) int pipe = intel_crtc->pipe; bool enabled; + if (intel_crtc->dpms_mode == mode) + return; + dev_priv->display.dpms(crtc, mode); intel_crtc->dpms_mode = mode; @@ -4915,7 +4918,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base; intel_crtc->cursor_addr = 0; - intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF; + intel_crtc->dpms_mode = -1; drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); intel_crtc->busy = false; -- cgit v1.2.3 From d9a9ffcc0d6d47bb0bdea19fc8e37577da3ee8bb Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 9 Sep 2010 11:58:02 -0700 Subject: drm/i915: don't enable self-refresh on Ironlake commit dd8849c8f59ec1cee4809a0c5e603e045abe860e upstream. We don't know how to enable it safely, especially as outputs turn on and off. When disabling LP1 we also need to make sure LP2 and 3 are already disabled. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=29173 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=29082 Reported-by: Chris Lord Signed-off-by: Jesse Barnes Tested-by: Daniel Vetter Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_reg.h | 8 ++++++++ drivers/gpu/drm/i915/intel_display.c | 6 ++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f9e17b10949c..bed6a5eb4e99 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2200,9 +2200,17 @@ #define WM1_LP_SR_EN (1<<31) #define WM1_LP_LATENCY_SHIFT 24 #define WM1_LP_LATENCY_MASK (0x7f<<24) +#define WM1_LP_FBC_LP1_MASK (0xf<<20) +#define WM1_LP_FBC_LP1_SHIFT 20 #define WM1_LP_SR_MASK (0x1ff<<8) #define WM1_LP_SR_SHIFT 8 #define WM1_LP_CURSOR_MASK (0x3f) +#define WM2_LP_ILK 0x4510c +#define WM2_LP_EN (1<<31) +#define WM3_LP_ILK 0x45110 +#define WM3_LP_EN (1<<31) +#define WM1S_LP_ILK 0x45120 +#define WM1S_LP_EN (1<<31) /* Memory latency timer register */ #define MLTR_ILK 0x11222 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 18f317f1dd01..ac38e4605ed2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3206,8 +3206,7 @@ static void ironlake_update_wm(struct drm_device *dev, int planea_clock, reg_value = I915_READ(WM1_LP_ILK); reg_value &= ~(WM1_LP_LATENCY_MASK | WM1_LP_SR_MASK | WM1_LP_CURSOR_MASK); - reg_value |= WM1_LP_SR_EN | - (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) | + reg_value |= (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) | (sr_wm << WM1_LP_SR_SHIFT) | cursor_wm; I915_WRITE(WM1_LP_ILK, reg_value); @@ -5425,6 +5424,9 @@ void intel_init_clock_gating(struct drm_device *dev) I915_WRITE(DISP_ARB_CTL, (I915_READ(DISP_ARB_CTL) | DISP_FBC_WM_DIS)); + I915_WRITE(WM3_LP_ILK, 0); + I915_WRITE(WM2_LP_ILK, 0); + I915_WRITE(WM1_LP_ILK, 0); } return; } else if (IS_G4X(dev)) { -- cgit v1.2.3 From 7e8ceff067f0482ee15a7b0b944f958a00a3fac3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Sep 2010 23:39:28 +0100 Subject: Revert "drm/i915: Allow LVDS on pipe A on gen4+" commit 12e8ba25ef52f19e7a42e61aecb3c1fef83b2a82 upstream. This reverts commit 0f3ee801b332d6ff22285386675fe5aaedf035c3. Enabling LVDS on pipe A was causing excessive wakeups on otherwise idle systems due to i915 interrupts. So restrict the LVDS to pipe B once more, whilst the issue is properly diagnosed. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=16307 Reported-and-tested-by: Enrico Bandiello Poked-by: Florian Mickler Signed-off-by: Chris Wilson Cc: Adam Jackson Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_lvds.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 0eab8df5bf7e..7d42ff16c4f6 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -988,8 +988,6 @@ void intel_lvds_init(struct drm_device *dev) intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); intel_encoder->crtc_mask = (1 << 1); - if (IS_I965G(dev)) - intel_encoder->crtc_mask |= (1 << 0); drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); connector->display_info.subpixel_order = SubPixelHorizontalRGB; -- cgit v1.2.3 From d3ad7717c9fbfd738308b39d47bf830aad23f408 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 9 Sep 2010 09:41:32 +0100 Subject: drm: Only decouple the old_fb from the crtc is we call mode_set* commit 356ad3cd616185631235ffb48b3efbf39f9923b3 upstream. Otherwise when disabling the output we switch to the new fb (which is likely NULL) and skip the call to mode_set -- leaking driver private state on the old_fb. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=29857 Reported-by: Sitsofe Wheeler Signed-off-by: Chris Wilson Cc: Dave Airlie Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_crtc_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 9b2a54117c91..25d70d63646e 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -610,13 +610,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) mode_changed = true; if (mode_changed) { - old_fb = set->crtc->fb; - set->crtc->fb = set->fb; set->crtc->enabled = (set->mode != NULL); if (set->mode != NULL) { DRM_DEBUG_KMS("attempting to set mode from" " userspace\n"); drm_mode_debug_printmodeline(set->mode); + old_fb = set->crtc->fb; + set->crtc->fb = set->fb; if (!drm_crtc_helper_set_mode(set->crtc, set->mode, set->x, set->y, old_fb)) { -- cgit v1.2.3 From db49cf204b56e7f067063a4c47a704eaf9a381ed Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 20 Sep 2010 13:59:09 -0700 Subject: Linux 2.6.35.5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 73ab03326440..11aaa51e2298 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 35 -EXTRAVERSION = .4 +EXTRAVERSION = .5 NAME = Sheep on Meth # *DOCUMENTATION* -- cgit v1.2.3 From 6c09969e0edfbc991387436eb011d5c7642b2b6a Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Mon, 6 Sep 2010 13:52:01 +0300 Subject: usb: musb_debugfs: don't use the struct file private_data field with seq_files commit 024cfa5943a7e89565c60b612d698c2bfb3da66a upstream. seq_files use the private_data field of a file struct for storing a seq_file structure, data should be stored in seq_file's own private field (e.g. file->private_data->private) Otherwise seq_release() will free the private data when the file is closed. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_debugfs.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c index c79a5e30d437..9e8639d4e862 100644 --- a/drivers/usb/musb/musb_debugfs.c +++ b/drivers/usb/musb/musb_debugfs.c @@ -195,15 +195,14 @@ static const struct file_operations musb_regdump_fops = { static int musb_test_mode_open(struct inode *inode, struct file *file) { - file->private_data = inode->i_private; - return single_open(file, musb_test_mode_show, inode->i_private); } static ssize_t musb_test_mode_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { - struct musb *musb = file->private_data; + struct seq_file *s = file->private_data; + struct musb *musb = s->private; u8 test = 0; char buf[18]; -- cgit v1.2.3 From 150e749ab763aef866fcc1d28e25371a39e7fcc1 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 15 Sep 2010 17:44:16 -0400 Subject: USB: serial/mos*: prevent reading uninitialized stack memory commit a0846f1868b11cd827bdfeaf4527d8b1b1c0b098 upstream. The TIOCGICOUNT device ioctl in both mos7720.c and mos7840.c allows unprivileged users to read uninitialized stack memory, because the "reserved" member of the serial_icounter_struct struct declared on the stack is not altered or zeroed before being copied back to the user. This patch takes care of it. Signed-off-by: Dan Rosenberg Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7720.c | 3 +++ drivers/usb/serial/mos7840.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 30922a7e3347..aa665817a272 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -2024,6 +2024,9 @@ static int mos7720_ioctl(struct tty_struct *tty, struct file *file, case TIOCGICOUNT: cnow = mos7720_port->icount; + + memset(&icount, 0, sizeof(struct serial_icounter_struct)); + icount.cts = cnow.cts; icount.dsr = cnow.dsr; icount.rng = cnow.rng; diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 1c9b6e9b2386..1a42bc213799 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2285,6 +2285,9 @@ static int mos7840_ioctl(struct tty_struct *tty, struct file *file, case TIOCGICOUNT: cnow = mos7840_port->icount; smp_rmb(); + + memset(&icount, 0, sizeof(struct serial_icounter_struct)); + icount.cts = cnow.cts; icount.dsr = cnow.dsr; icount.rng = cnow.rng; -- cgit v1.2.3 From 5d92da4418de42f1f85920f84d81a66bb559727e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 1 Sep 2010 18:06:39 -0700 Subject: bridge: Clear INET control block of SKBs passed into ip_fragment(). [ Upstream commit 4ce6b9e1621c187a32a47a17bf6be93b1dc4a3df ] In a similar vain to commit 17762060c25590bfddd68cc1131f28ec720f405f ("bridge: Clear IPCB before possible entry into IP stack") Any time we call into the IP stack we have to make sure the state there is as expected by the ipv4 code. With help from Eric Dumazet and Herbert Xu. Reported-by: Brandan Das Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/bridge/br_netfilter.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 8fb75f89c4aa..e759b892a71c 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -749,9 +749,11 @@ static int br_nf_dev_queue_xmit(struct sk_buff *skb) { if (skb->nfct != NULL && skb->protocol == htons(ETH_P_IP) && skb->len + nf_bridge_mtu_reduction(skb) > skb->dev->mtu && - !skb_is_gso(skb)) + !skb_is_gso(skb)) { + /* BUG: Should really parse the IP options here. */ + memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); return ip_fragment(skb, br_dev_queue_push_xmit); - else + } else return br_dev_queue_push_xmit(skb); } #else -- cgit v1.2.3 From 76dcdc683e9ab26c0227d9f40b390edba9fca621 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 1 Sep 2010 00:50:51 +0000 Subject: gro: fix different skb headrooms [ Upstream commit 3d3be4333fdf6faa080947b331a6a19bce1a4f57 ] Packets entering GRO might have different headrooms, even for a given flow (because of implementation details in drivers, like copybreak). We cant force drivers to deliver packets with a fixed headroom. 1) fix skb_segment() skb_segment() makes the false assumption headrooms of fragments are same than the head. When CHECKSUM_PARTIAL is used, this can give csum_start errors, and crash later in skb_copy_and_csum_dev() 2) allocate a minimal skb for head of frag_list skb_gro_receive() uses netdev_alloc_skb(headroom + skb_gro_offset(p)) to allocate a fresh skb. This adds NET_SKB_PAD to a padding already provided by netdevice, depending on various things, like copybreak. Use alloc_skb() to allocate an exact padding, to reduce cache line needs: NET_SKB_PAD + NET_IP_ALIGN bugzilla : https://bugzilla.kernel.org/show_bug.cgi?id=16626 Many thanks to Plamen Petrov, testing many debugging patches ! With help of Jarek Poplawski. Reported-by: Plamen Petrov Signed-off-by: Eric Dumazet CC: Jarek Poplawski Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/skbuff.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index ce88293a34e2..5046b9542260 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2574,6 +2574,10 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) __copy_skb_header(nskb, skb); nskb->mac_len = skb->mac_len; + /* nskb and skb might have different headroom */ + if (nskb->ip_summed == CHECKSUM_PARTIAL) + nskb->csum_start += skb_headroom(nskb) - headroom; + skb_reset_mac_header(nskb); skb_set_network_header(nskb, skb->mac_len); nskb->transport_header = (nskb->network_header + @@ -2703,8 +2707,8 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) } else if (skb_gro_len(p) != pinfo->gso_size) return -E2BIG; - headroom = skb_headroom(p); - nskb = netdev_alloc_skb(p->dev, headroom + skb_gro_offset(p)); + headroom = NET_SKB_PAD + NET_IP_ALIGN; + nskb = alloc_skb(headroom + skb_gro_offset(p), GFP_ATOMIC); if (unlikely(!nskb)) return -ENOMEM; -- cgit v1.2.3 From 88c2651de40107913811814405591d9077d71b02 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Sat, 4 Sep 2010 10:34:29 +0000 Subject: gro: Re-fix different skb headrooms [ Upstream commit 64289c8e6851bca0e589e064c9a5c9fbd6ae5dd4 ] The patch: "gro: fix different skb headrooms" in its part: "2) allocate a minimal skb for head of frag_list" is buggy. The copied skb has p->data set at the ip header at the moment, and skb_gro_offset is the length of ip + tcp headers. So, after the change the length of mac header is skipped. Later skb_set_mac_header() sets it into the NET_SKB_PAD area (if it's long enough) and ip header is misaligned at NET_SKB_PAD + NET_IP_ALIGN offset. There is no reason to assume the original skb was wrongly allocated, so let's copy it as it was. bugzilla : https://bugzilla.kernel.org/show_bug.cgi?id=16626 fixes commit: 3d3be4333fdf6faa080947b331a6a19bce1a4f57 Reported-by: Plamen Petrov Signed-off-by: Jarek Poplawski CC: Eric Dumazet Acked-by: Eric Dumazet Tested-by: Plamen Petrov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/skbuff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 5046b9542260..a586e8918a62 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2707,7 +2707,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) } else if (skb_gro_len(p) != pinfo->gso_size) return -E2BIG; - headroom = NET_SKB_PAD + NET_IP_ALIGN; + headroom = skb_headroom(p); nskb = alloc_skb(headroom + skb_gro_offset(p), GFP_ATOMIC); if (unlikely(!nskb)) return -ENOMEM; -- cgit v1.2.3 From 2f2c0c6440110d7436f202ecf918734243e7b870 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 30 Aug 2010 18:35:24 -0700 Subject: irda: Correctly clean up self->ias_obj on irda_bind() failure. [ Upstream commit 628e300cccaa628d8fb92aa28cb7530a3d5f2257 ] If irda_open_tsap() fails, the irda_bind() code tries to destroy the ->ias_obj object by hand, but does so wrongly. In particular, it fails to a) release the hashbin attached to the object and b) reset the self->ias_obj pointer to NULL. Fix both problems by using irias_delete_object() and explicitly setting self->ias_obj to NULL, just as irda_release() does. Reported-by: Tavis Ormandy Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/irda/af_irda.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 79986a674f6e..fd55b5135de5 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -824,8 +824,8 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name); if (err < 0) { - kfree(self->ias_obj->name); - kfree(self->ias_obj); + irias_delete_object(self->ias_obj); + self->ias_obj = NULL; goto out; } -- cgit v1.2.3 From 3289b85e643814c06b3196bafeda3a44d4d75fe8 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 16 Aug 2010 03:25:00 +0000 Subject: rds: fix a leak of kernel memory [ Upstream commit f037590fff3005ce8a1513858d7d44f50053cc8f ] struct rds_rdma_notify contains a 32 bits hole on 64bit arches, make sure it is zeroed before copying it to user. Signed-off-by: Eric Dumazet CC: Andy Grover Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/rds/recv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/rds/recv.c b/net/rds/recv.c index 795a00b7f2cb..c93588c2d553 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c @@ -297,7 +297,7 @@ static int rds_still_queued(struct rds_sock *rs, struct rds_incoming *inc, int rds_notify_queue_get(struct rds_sock *rs, struct msghdr *msghdr) { struct rds_notifier *notifier; - struct rds_rdma_notify cmsg; + struct rds_rdma_notify cmsg = { 0 }; /* fill holes with zero */ unsigned int count = 0, max_messages = ~0U; unsigned long flags; LIST_HEAD(copy); -- cgit v1.2.3 From 515b723e04cb4df7f96c59dee019d126df707fc0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 14 Sep 2010 21:41:20 -0700 Subject: net: RPS needs to depend upon USE_GENERIC_SMP_HELPERS [ Upstream commit 6dcbc12290abb452a5e42713faa6461b248e2f55 ] You cannot invoke __smp_call_function_single() unless the architecture sets this symbol. Reported-by: Daniel Hellstrom Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/Kconfig b/net/Kconfig index 0d68b40fc0e6..a44092e90e8c 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -206,7 +206,7 @@ source "net/dcb/Kconfig" config RPS boolean - depends on SMP && SYSFS + depends on SMP && SYSFS && USE_GENERIC_SMP_HELPERS default y menu "Network testing" -- cgit v1.2.3 From fd31b5dcb8c69c007705caa9dccdaa371f21b4f0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 25 Aug 2010 02:27:49 -0700 Subject: tcp: Combat per-cpu skew in orphan tests. [ Upstream commit ad1af0fedba14f82b240a03fe20eb9b2fdbd0357 ] As reported by Anton Blanchard when we use percpu_counter_read_positive() to make our orphan socket limit checks, the check can be off by up to num_cpus_online() * batch (which is 32 by default) which on a 128 cpu machine can be as large as the default orphan limit itself. Fix this by doing the full expensive sum check if the optimized check triggers. Reported-by: Anton Blanchard Signed-off-by: David S. Miller Acked-by: Eric Dumazet Signed-off-by: Greg Kroah-Hartman --- include/net/tcp.h | 18 ++++++++++++++---- net/ipv4/tcp.c | 5 +---- net/ipv4/tcp_timer.c | 8 ++++---- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index a1449144848a..338ee3ff5a02 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -268,11 +268,21 @@ static inline int between(__u32 seq1, __u32 seq2, __u32 seq3) return seq3 - seq2 >= seq1 - seq2; } -static inline int tcp_too_many_orphans(struct sock *sk, int num) +static inline bool tcp_too_many_orphans(struct sock *sk, int shift) { - return (num > sysctl_tcp_max_orphans) || - (sk->sk_wmem_queued > SOCK_MIN_SNDBUF && - atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2]); + struct percpu_counter *ocp = sk->sk_prot->orphan_count; + int orphans = percpu_counter_read_positive(ocp); + + if (orphans << shift > sysctl_tcp_max_orphans) { + orphans = percpu_counter_sum_positive(ocp); + if (orphans << shift > sysctl_tcp_max_orphans) + return true; + } + + if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF && + atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2]) + return true; + return false; } /* syncookies: remember time of last synqueue overflow */ diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index c259714c5596..dfe12d6bad92 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2002,11 +2002,8 @@ adjudge_to_death: } } if (sk->sk_state != TCP_CLOSE) { - int orphan_count = percpu_counter_read_positive( - sk->sk_prot->orphan_count); - sk_mem_reclaim(sk); - if (tcp_too_many_orphans(sk, orphan_count)) { + if (tcp_too_many_orphans(sk, 0)) { if (net_ratelimit()) printk(KERN_INFO "TCP: too many of orphaned " "sockets\n"); diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 440a5c6004f6..7abd922b205b 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -67,18 +67,18 @@ static void tcp_write_err(struct sock *sk) static int tcp_out_of_resources(struct sock *sk, int do_reset) { struct tcp_sock *tp = tcp_sk(sk); - int orphans = percpu_counter_read_positive(&tcp_orphan_count); + int shift = 0; /* If peer does not open window for long time, or did not transmit * anything for long time, penalize it. */ if ((s32)(tcp_time_stamp - tp->lsndtime) > 2*TCP_RTO_MAX || !do_reset) - orphans <<= 1; + shift++; /* If some dubious ICMP arrived, penalize even more. */ if (sk->sk_err_soft) - orphans <<= 1; + shift++; - if (tcp_too_many_orphans(sk, orphans)) { + if (tcp_too_many_orphans(sk, shift)) { if (net_ratelimit()) printk(KERN_INFO "Out of socket memory\n"); -- cgit v1.2.3 From 8411b2debbd772b2dc156f06d7da73cdcbd08d35 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 25 Aug 2010 23:02:17 -0700 Subject: tcp: fix three tcp sysctls tuning [ Upstream commit c5ed63d66f24fd4f7089b5a6e087b0ce7202aa8e ] As discovered by Anton Blanchard, current code to autotune tcp_death_row.sysctl_max_tw_buckets, sysctl_tcp_max_orphans and sysctl_max_syn_backlog makes little sense. The bigger a page is, the less tcp_max_orphans is : 4096 on a 512GB machine in Anton's case. (tcp_hashinfo.bhash_size * sizeof(struct inet_bind_hashbucket)) is much bigger if spinlock debugging is on. Its wrong to select bigger limits in this case (where kernel structures are also bigger) bhash_size max is 65536, and we get this value even for small machines. A better ground is to use size of ehash table, this also makes code shorter and more obvious. Based on a patch from Anton, and another from David. Reported-and-tested-by: Anton Blanchard Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index dfe12d6bad92..952ba943c77f 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -3193,7 +3193,7 @@ void __init tcp_init(void) { struct sk_buff *skb = NULL; unsigned long nr_pages, limit; - int order, i, max_share; + int i, max_share, cnt; unsigned long jiffy = jiffies; BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); @@ -3242,22 +3242,12 @@ void __init tcp_init(void) INIT_HLIST_HEAD(&tcp_hashinfo.bhash[i].chain); } - /* Try to be a bit smarter and adjust defaults depending - * on available memory. - */ - for (order = 0; ((1 << order) << PAGE_SHIFT) < - (tcp_hashinfo.bhash_size * sizeof(struct inet_bind_hashbucket)); - order++) - ; - if (order >= 4) { - tcp_death_row.sysctl_max_tw_buckets = 180000; - sysctl_tcp_max_orphans = 4096 << (order - 4); - sysctl_max_syn_backlog = 1024; - } else if (order < 3) { - tcp_death_row.sysctl_max_tw_buckets >>= (3 - order); - sysctl_tcp_max_orphans >>= (3 - order); - sysctl_max_syn_backlog = 128; - } + + cnt = tcp_hashinfo.ehash_mask + 1; + + tcp_death_row.sysctl_max_tw_buckets = cnt / 2; + sysctl_tcp_max_orphans = cnt / 2; + sysctl_max_syn_backlog = max(128, cnt / 256); /* Set the pressure threshold to be a fraction of global memory that * is up to 1/2 at 256 MB, decreasing toward zero with the amount of -- cgit v1.2.3 From 5bc7298fc100540046e9e252d2fc0e4606d39b44 Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Tue, 24 Aug 2010 16:05:48 +0000 Subject: tcp: select(writefds) don't hang up when a peer close connection [ Upstream commit d84ba638e4ba3c40023ff997aa5e8d3ed002af36 ] This issue come from ruby language community. Below test program hang up when only run on Linux. % uname -mrsv Linux 2.6.26-2-486 #1 Sat Dec 26 08:37:39 UTC 2009 i686 % ruby -rsocket -ve ' BasicSocket.do_not_reverse_lookup = true serv = TCPServer.open("127.0.0.1", 0) s1 = TCPSocket.open("127.0.0.1", serv.addr[1]) s2 = serv.accept s2.close s1.write("a") rescue p $! s1.write("a") rescue p $! Thread.new { s1.write("a") }.join' ruby 1.9.3dev (2010-07-06 trunk 28554) [i686-linux] # [Hang Here] FreeBSD, Solaris, Mac doesn't. because Ruby's write() method call select() internally. and tcp_poll has a bug. SUS defined 'ready for writing' of select() as following. | A descriptor shall be considered ready for writing when a call to an output | function with O_NONBLOCK clear would not block, whether or not the function | would transfer data successfully. That said, EPIPE situation is clearly one of 'ready for writing'. We don't have read-side issue because tcp_poll() already has read side shutdown care. | if (sk->sk_shutdown & RCV_SHUTDOWN) | mask |= POLLIN | POLLRDNORM | POLLRDHUP; So, Let's insert same logic in write side. - reference url http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/31065 http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/31068 Signed-off-by: KOSAKI Motohiro Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 952ba943c77f..c88ca260585d 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -453,7 +453,8 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) mask |= POLLOUT | POLLWRNORM; } - } + } else + mask |= POLLOUT | POLLWRNORM; if (tp->urg_data & TCP_URG_VALID) mask |= POLLPRI; -- cgit v1.2.3 From 4275a88aa5891aadb1227631d9e602a1f66f347f Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Wed, 15 Sep 2010 10:27:52 -0700 Subject: tcp: Prevent overzealous packetization by SWS logic. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 01f83d69844d307be2aa6fea88b0e8fe5cbdb2f4 ] If peer uses tiny MSS (say, 75 bytes) and similarly tiny advertised window, the SWS logic will packetize to half the MSS unnecessarily. This causes problems with some embedded devices. However for large MSS devices we do want to half-MSS packetize otherwise we never get enough packets into the pipe for things like fast retransmit and recovery to work. Be careful also to handle the case where MSS > window, otherwise we'll never send until the probe timer. Reported-by: ツ Leandro Melo de Sales Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/tcp.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 338ee3ff5a02..e824cf036114 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -519,8 +519,22 @@ extern unsigned int tcp_current_mss(struct sock *sk); /* Bound MSS / TSO packet size with the half of the window */ static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize) { - if (tp->max_window && pktsize > (tp->max_window >> 1)) - return max(tp->max_window >> 1, 68U - tp->tcp_header_len); + int cutoff; + + /* When peer uses tiny windows, there is no use in packetizing + * to sub-MSS pieces for the sake of SWS or making sure there + * are enough packets in the pipe for fast recovery. + * + * On the other hand, for extremely large MSS devices, handling + * smaller than MSS windows in this way does make sense. + */ + if (tp->max_window >= 512) + cutoff = (tp->max_window >> 1); + else + cutoff = tp->max_window; + + if (cutoff && pktsize > cutoff) + return max_t(int, cutoff, 68U - tp->tcp_header_len); else return pktsize; } -- cgit v1.2.3 From 749f63ed9bf702e588000f1d1ce6290e6c156289 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 8 Sep 2010 05:08:44 +0000 Subject: udp: add rehash on connect() commit 719f835853a92f6090258114a72ffe41f09155cd upstream commit 30fff923 introduced in linux-2.6.33 (udp: bind() optimisation) added a secondary hash on UDP, hashed on (local addr, local port). Problem is that following sequence : fd = socket(...) connect(fd, &remote, ...) not only selects remote end point (address and port), but also sets local address, while UDP stack stored in secondary hash table the socket while its local address was INADDR_ANY (or ipv6 equivalent) Sequence is : - autobind() : choose a random local port, insert socket in hash tables [while local address is INADDR_ANY] - connect() : set remote address and port, change local address to IP given by a route lookup. When an incoming UDP frame comes, if more than 10 sockets are found in primary hash table, we switch to secondary table, and fail to find socket because its local address changed. One solution to this problem is to rehash datagram socket if needed. We add a new rehash(struct socket *) method in "struct proto", and implement this method for UDP v4 & v6, using a common helper. This rehashing only takes care of secondary hash table, since primary hash (based on local port only) is not changed. Reported-by: Krzysztof Piotr Oledzki Signed-off-by: Eric Dumazet Tested-by: Krzysztof Piotr Oledzki Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/sock.h | 1 + include/net/udp.h | 1 + net/ipv4/datagram.c | 5 ++++- net/ipv4/udp.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ net/ipv6/datagram.c | 7 ++++++- net/ipv6/udp.c | 10 ++++++++++ 6 files changed, 66 insertions(+), 2 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 0a691ea7654a..e2a9f591a0e3 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -749,6 +749,7 @@ struct proto { /* Keeping track of sk's, looking them up, and port selection methods. */ void (*hash)(struct sock *sk); void (*unhash)(struct sock *sk); + void (*rehash)(struct sock *sk); int (*get_port)(struct sock *sk, unsigned short snum); /* Keeping track of sockets in use */ diff --git a/include/net/udp.h b/include/net/udp.h index 5348d80b25bb..4201dc8724ca 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -151,6 +151,7 @@ static inline void udp_lib_hash(struct sock *sk) } extern void udp_lib_unhash(struct sock *sk); +extern void udp_lib_rehash(struct sock *sk, u16 new_hash); static inline void udp_lib_close(struct sock *sk, long timeout) { diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index fb2465811b48..31cafd491dde 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -62,8 +62,11 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) } if (!inet->inet_saddr) inet->inet_saddr = rt->rt_src; /* Update source address */ - if (!inet->inet_rcv_saddr) + if (!inet->inet_rcv_saddr) { inet->inet_rcv_saddr = rt->rt_src; + if (sk->sk_prot->rehash) + sk->sk_prot->rehash(sk); + } inet->inet_daddr = rt->rt_dst; inet->inet_dport = usin->sin_port; sk->sk_state = TCP_ESTABLISHED; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index eec4ff456e33..434dd6777419 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1260,6 +1260,49 @@ void udp_lib_unhash(struct sock *sk) } EXPORT_SYMBOL(udp_lib_unhash); +/* + * inet_rcv_saddr was changed, we must rehash secondary hash + */ +void udp_lib_rehash(struct sock *sk, u16 newhash) +{ + if (sk_hashed(sk)) { + struct udp_table *udptable = sk->sk_prot->h.udp_table; + struct udp_hslot *hslot, *hslot2, *nhslot2; + + hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash); + nhslot2 = udp_hashslot2(udptable, newhash); + udp_sk(sk)->udp_portaddr_hash = newhash; + if (hslot2 != nhslot2) { + hslot = udp_hashslot(udptable, sock_net(sk), + udp_sk(sk)->udp_port_hash); + /* we must lock primary chain too */ + spin_lock_bh(&hslot->lock); + + spin_lock(&hslot2->lock); + hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node); + hslot2->count--; + spin_unlock(&hslot2->lock); + + spin_lock(&nhslot2->lock); + hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node, + &nhslot2->head); + nhslot2->count++; + spin_unlock(&nhslot2->lock); + + spin_unlock_bh(&hslot->lock); + } + } +} +EXPORT_SYMBOL(udp_lib_rehash); + +static void udp_v4_rehash(struct sock *sk) +{ + u16 new_hash = udp4_portaddr_hash(sock_net(sk), + inet_sk(sk)->inet_rcv_saddr, + inet_sk(sk)->inet_num); + udp_lib_rehash(sk, new_hash); +} + static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) { int rc; @@ -1843,6 +1886,7 @@ struct proto udp_prot = { .backlog_rcv = __udp_queue_rcv_skb, .hash = udp_lib_hash, .unhash = udp_lib_unhash, + .rehash = udp_v4_rehash, .get_port = udp_v4_get_port, .memory_allocated = &udp_memory_allocated, .sysctl_mem = sysctl_udp_mem, diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 712684687c9a..0e3754a1237e 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -104,9 +104,12 @@ ipv4_connected: if (ipv6_addr_any(&np->saddr)) ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr); - if (ipv6_addr_any(&np->rcv_saddr)) + if (ipv6_addr_any(&np->rcv_saddr)) { ipv6_addr_set_v4mapped(inet->inet_rcv_saddr, &np->rcv_saddr); + if (sk->sk_prot->rehash) + sk->sk_prot->rehash(sk); + } goto out; } @@ -191,6 +194,8 @@ ipv4_connected: if (ipv6_addr_any(&np->rcv_saddr)) { ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src); inet->inet_rcv_saddr = LOOPBACK4_IPV6; + if (sk->sk_prot->rehash) + sk->sk_prot->rehash(sk); } ip6_dst_store(sk, dst, diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 87be58673b55..97e1214d7ff9 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -111,6 +111,15 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum) return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal, hash2_nulladdr); } +static void udp_v6_rehash(struct sock *sk) +{ + u16 new_hash = udp6_portaddr_hash(sock_net(sk), + &inet6_sk(sk)->rcv_saddr, + inet_sk(sk)->inet_num); + + udp_lib_rehash(sk, new_hash); +} + static inline int compute_score(struct sock *sk, struct net *net, unsigned short hnum, struct in6_addr *saddr, __be16 sport, @@ -1452,6 +1461,7 @@ struct proto udpv6_prot = { .backlog_rcv = udpv6_queue_rcv_skb, .hash = udp_lib_hash, .unhash = udp_lib_unhash, + .rehash = udp_v6_rehash, .get_port = udp_v6_get_port, .memory_allocated = &udp_memory_allocated, .sysctl_mem = sysctl_udp_mem, -- cgit v1.2.3 From 4aeda42a1b443d705980c85184cca7f8f28625bf Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sat, 4 Sep 2010 01:34:28 +0000 Subject: UNIX: Do not loop forever at unix_autobind(). [ Upstream commit a9117426d0fcc05a194f728159a2d43df43c7add ] We assumed that unix_autobind() never fails if kzalloc() succeeded. But unix_autobind() allows only 1048576 names. If /proc/sys/fs/file-max is larger than 1048576 (e.g. systems with more than 10GB of RAM), a local user can consume all names using fork()/socket()/bind(). If all names are in use, those who call bind() with addr_len == sizeof(short) or connect()/sendmsg() with setsockopt(SO_PASSCRED) will continue while (1) yield(); loop at unix_autobind() till a name becomes available. This patch adds a loop counter in order to give up after 1048576 attempts. Calling yield() for once per 256 attempts may not be sufficient when many names are already in use, for __unix_find_socket_byname() can take long time under such circumstance. Therefore, this patch also adds cond_resched() call. Note that currently a local user can consume 2GB of kernel memory if the user is allowed to create and autobind 1048576 UNIX domain sockets. We should consider adding some restriction for autobind operation. Signed-off-by: Tetsuo Handa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/unix/af_unix.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index fef2cc5e9d2b..617bea46486d 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -673,6 +673,7 @@ static int unix_autobind(struct socket *sock) static u32 ordernum = 1; struct unix_address *addr; int err; + unsigned int retries = 0; mutex_lock(&u->readlock); @@ -698,9 +699,17 @@ retry: if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type, addr->hash)) { spin_unlock(&unix_table_lock); - /* Sanity yield. It is unusual case, but yet... */ - if (!(ordernum&0xFF)) - yield(); + /* + * __unix_find_socket_byname() may take long time if many names + * are already in use. + */ + cond_resched(); + /* Give up if all names seems to be in use. */ + if (retries++ == 0xFFFFF) { + err = -ENOSPC; + kfree(addr); + goto out; + } goto retry; } addr->hash ^= sk->sk_type; -- cgit v1.2.3 From 2974d51279e5437f5b34a5163d1d835586488946 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 25 Aug 2010 23:44:35 +0000 Subject: l2tp: test for ethernet header in l2tp_eth_dev_recv() [ Upstream commit bfc960a8eec023a170a80697fe65157cd4f44f81 ] close https://bugzilla.kernel.org/show_bug.cgi?id=16529 Before calling dev_forward_skb(), we should make sure skb head contains at least an ethernet header, even if length included in upper layer said so. Use pskb_may_pull() to make sure this ethernet header is present in skb head. Reported-by: Thomas Heil Reported-by: Ian Campbell Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/l2tp/l2tp_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 58c6c4cda73b..1ae697681bc7 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -132,7 +132,7 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb, printk("\n"); } - if (data_len < ETH_HLEN) + if (!pskb_may_pull(skb, sizeof(ETH_HLEN))) goto error; secpath_reset(skb); -- cgit v1.2.3 From 1919a55fb8c709f11224a964bb6a93a267daad14 Mon Sep 17 00:00:00 2001 From: Jianzhao Wang Date: Wed, 8 Sep 2010 14:35:43 -0700 Subject: net: blackhole route should always be recalculated [ Upstream commit ae2688d59b5f861dc70a091d003773975d2ae7fb ] Blackhole routes are used when xfrm_lookup() returns -EREMOTE (error triggered by IKE for example), hence this kind of route is always temporary and so we should check if a better route exists for next packets. Bug has been introduced by commit d11a4dc18bf41719c9f0d7ed494d295dd2973b92. Signed-off-by: Jianzhao Wang Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/route.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 560acc677ce4..0189deb093d7 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2741,6 +2741,11 @@ slow_output: EXPORT_SYMBOL_GPL(__ip_route_output_key); +static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 cookie) +{ + return NULL; +} + static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) { } @@ -2749,7 +2754,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = { .family = AF_INET, .protocol = cpu_to_be16(ETH_P_IP), .destroy = ipv4_dst_destroy, - .check = ipv4_dst_check, + .check = ipv4_blackhole_dst_check, .update_pmtu = ipv4_rt_blackhole_update_pmtu, .entries = ATOMIC_INIT(0), }; -- cgit v1.2.3 From df7b44d7704fd1a1f3f6af399587bc15732490b0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 Aug 2010 23:10:57 -0700 Subject: sparc64: Get rid of indirect p1275 PROM call buffer. [ Upstream commit 25edd6946a1d74e5e77813c2324a0908c68bcf9e ] This is based upon a report by Meelis Roos showing that it's possible that we'll try to fetch a property that is 32K in size with some devices. With the current fixed 3K buffer we use for moving data in and out of the firmware during PROM calls, that simply won't work. In fact, it will scramble random kernel data during bootup. The reasoning behind the temporary buffer is entirely historical. It used to be the case that we had problems referencing dynamic kernel memory (including the stack) early in the boot process before we explicitly told the firwmare to switch us over to the kernel trap table. So what we did was always give the firmware buffers that were locked into the main kernel image. But we no longer have problems like that, so get rid of all of this indirect bounce buffering. Besides fixing Meelis's bug, this also makes the kernel data about 3K smaller. It was also discovered during these conversions that the implementation of prom_retain() was completely wrong, so that was fixed here as well. Currently that interface is not in use. Reported-by: Meelis Roos Tested-by: Meelis Roos Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/include/asm/oplib_64.h | 27 +--- arch/sparc/prom/cif.S | 16 +- arch/sparc/prom/console_64.c | 48 ++++-- arch/sparc/prom/devops_64.c | 36 ++++- arch/sparc/prom/misc_64.c | 314 ++++++++++++++++++++++++++------------ arch/sparc/prom/p1275.c | 102 +------------ arch/sparc/prom/tree_64.c | 210 ++++++++++++++++++------- 7 files changed, 456 insertions(+), 297 deletions(-) diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h index a5db0317b5fb..3e0b2d62303d 100644 --- a/arch/sparc/include/asm/oplib_64.h +++ b/arch/sparc/include/asm/oplib_64.h @@ -185,9 +185,8 @@ extern int prom_getunumber(int syndrome_code, char *buf, int buflen); /* Retain physical memory to the caller across soft resets. */ -extern unsigned long prom_retain(const char *name, - unsigned long pa_low, unsigned long pa_high, - long size, long align); +extern int prom_retain(const char *name, unsigned long size, + unsigned long align, unsigned long *paddr); /* Load explicit I/D TLB entries into the calling processor. */ extern long prom_itlb_load(unsigned long index, @@ -287,26 +286,6 @@ extern void prom_sun4v_guest_soft_state(void); extern int prom_ihandle2path(int handle, char *buffer, int bufsize); /* Client interface level routines. */ -extern long p1275_cmd(const char *, long, ...); - -#if 0 -#define P1275_SIZE(x) ((((long)((x) / 32)) << 32) | (x)) -#else -#define P1275_SIZE(x) x -#endif - -/* We support at most 16 input and 1 output argument */ -#define P1275_ARG_NUMBER 0 -#define P1275_ARG_IN_STRING 1 -#define P1275_ARG_OUT_BUF 2 -#define P1275_ARG_OUT_32B 3 -#define P1275_ARG_IN_FUNCTION 4 -#define P1275_ARG_IN_BUF 5 -#define P1275_ARG_IN_64B 6 - -#define P1275_IN(x) ((x) & 0xf) -#define P1275_OUT(x) (((x) << 4) & 0xf0) -#define P1275_INOUT(i,o) (P1275_IN(i)|P1275_OUT(o)) -#define P1275_ARG(n,x) ((x) << ((n)*3 + 8)) +extern void p1275_cmd_direct(unsigned long *); #endif /* !(__SPARC64_OPLIB_H) */ diff --git a/arch/sparc/prom/cif.S b/arch/sparc/prom/cif.S index 5f27ad779c0c..9c86b4b7d429 100644 --- a/arch/sparc/prom/cif.S +++ b/arch/sparc/prom/cif.S @@ -9,18 +9,18 @@ #include .text - .globl prom_cif_interface -prom_cif_interface: - sethi %hi(p1275buf), %o0 - or %o0, %lo(p1275buf), %o0 - ldx [%o0 + 0x010], %o1 ! prom_cif_stack - save %o1, -192, %sp - ldx [%i0 + 0x008], %l2 ! prom_cif_handler + .globl prom_cif_direct +prom_cif_direct: + sethi %hi(p1275buf), %o1 + or %o1, %lo(p1275buf), %o1 + ldx [%o1 + 0x0010], %o2 ! prom_cif_stack + save %o2, -192, %sp + ldx [%i1 + 0x0008], %l2 ! prom_cif_handler mov %g4, %l0 mov %g5, %l1 mov %g6, %l3 call %l2 - add %i0, 0x018, %o0 ! prom_args + mov %i0, %o0 ! prom_args mov %l0, %g4 mov %l1, %g5 mov %l3, %g6 diff --git a/arch/sparc/prom/console_64.c b/arch/sparc/prom/console_64.c index f55d58a8a156..10322dc2f557 100644 --- a/arch/sparc/prom/console_64.c +++ b/arch/sparc/prom/console_64.c @@ -21,14 +21,22 @@ extern int prom_stdin, prom_stdout; inline int prom_nbgetchar(void) { + unsigned long args[7]; char inc; - if (p1275_cmd("read", P1275_ARG(1,P1275_ARG_OUT_BUF)| - P1275_INOUT(3,1), - prom_stdin, &inc, P1275_SIZE(1)) == 1) + args[0] = (unsigned long) "read"; + args[1] = 3; + args[2] = 1; + args[3] = (unsigned int) prom_stdin; + args[4] = (unsigned long) &inc; + args[5] = 1; + args[6] = (unsigned long) -1; + + p1275_cmd_direct(args); + + if (args[6] == 1) return inc; - else - return -1; + return -1; } /* Non blocking put character to console device, returns -1 if @@ -37,12 +45,22 @@ prom_nbgetchar(void) inline int prom_nbputchar(char c) { + unsigned long args[7]; char outc; outc = c; - if (p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)| - P1275_INOUT(3,1), - prom_stdout, &outc, P1275_SIZE(1)) == 1) + + args[0] = (unsigned long) "write"; + args[1] = 3; + args[2] = 1; + args[3] = (unsigned int) prom_stdout; + args[4] = (unsigned long) &outc; + args[5] = 1; + args[6] = (unsigned long) -1; + + p1275_cmd_direct(args); + + if (args[6] == 1) return 0; else return -1; @@ -67,7 +85,15 @@ prom_putchar(char c) void prom_puts(const char *s, int len) { - p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)| - P1275_INOUT(3,1), - prom_stdout, s, P1275_SIZE(len)); + unsigned long args[7]; + + args[0] = (unsigned long) "write"; + args[1] = 3; + args[2] = 1; + args[3] = (unsigned int) prom_stdout; + args[4] = (unsigned long) s; + args[5] = len; + args[6] = (unsigned long) -1; + + p1275_cmd_direct(args); } diff --git a/arch/sparc/prom/devops_64.c b/arch/sparc/prom/devops_64.c index 9dbd803e46e1..a017119e7ef1 100644 --- a/arch/sparc/prom/devops_64.c +++ b/arch/sparc/prom/devops_64.c @@ -18,16 +18,32 @@ int prom_devopen(const char *dstr) { - return p1275_cmd ("open", P1275_ARG(0,P1275_ARG_IN_STRING)| - P1275_INOUT(1,1), - dstr); + unsigned long args[5]; + + args[0] = (unsigned long) "open"; + args[1] = 1; + args[2] = 1; + args[3] = (unsigned long) dstr; + args[4] = (unsigned long) -1; + + p1275_cmd_direct(args); + + return (int) args[4]; } /* Close the device described by device handle 'dhandle'. */ int prom_devclose(int dhandle) { - p1275_cmd ("close", P1275_INOUT(1,0), dhandle); + unsigned long args[4]; + + args[0] = (unsigned long) "close"; + args[1] = 1; + args[2] = 0; + args[3] = (unsigned int) dhandle; + + p1275_cmd_direct(args); + return 0; } @@ -37,5 +53,15 @@ prom_devclose(int dhandle) void prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo) { - p1275_cmd ("seek", P1275_INOUT(3,1), dhandle, seekhi, seeklo); + unsigned long args[7]; + + args[0] = (unsigned long) "seek"; + args[1] = 3; + args[2] = 1; + args[3] = (unsigned int) dhandle; + args[4] = seekhi; + args[5] = seeklo; + args[6] = (unsigned long) -1; + + p1275_cmd_direct(args); } diff --git a/arch/sparc/prom/misc_64.c b/arch/sparc/prom/misc_64.c index 39fc6af21b7c..6cb1581d6aef 100644 --- a/arch/sparc/prom/misc_64.c +++ b/arch/sparc/prom/misc_64.c @@ -20,10 +20,17 @@ int prom_service_exists(const char *service_name) { - int err = p1275_cmd("test", P1275_ARG(0, P1275_ARG_IN_STRING) | - P1275_INOUT(1, 1), service_name); + unsigned long args[5]; - if (err) + args[0] = (unsigned long) "test"; + args[1] = 1; + args[2] = 1; + args[3] = (unsigned long) service_name; + args[4] = (unsigned long) -1; + + p1275_cmd_direct(args); + + if (args[4]) return 0; return 1; } @@ -31,30 +38,47 @@ int prom_service_exists(const char *service_name) void prom_sun4v_guest_soft_state(void) { const char *svc = "SUNW,soft-state-supported"; + unsigned long args[3]; if (!prom_service_exists(svc)) return; - p1275_cmd(svc, P1275_INOUT(0, 0)); + args[0] = (unsigned long) svc; + args[1] = 0; + args[2] = 0; + p1275_cmd_direct(args); } /* Reset and reboot the machine with the command 'bcommand'. */ void prom_reboot(const char *bcommand) { + unsigned long args[4]; + #ifdef CONFIG_SUN_LDOMS if (ldom_domaining_enabled) ldom_reboot(bcommand); #endif - p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) | - P1275_INOUT(1, 0), bcommand); + args[0] = (unsigned long) "boot"; + args[1] = 1; + args[2] = 0; + args[3] = (unsigned long) bcommand; + + p1275_cmd_direct(args); } /* Forth evaluate the expression contained in 'fstring'. */ void prom_feval(const char *fstring) { + unsigned long args[5]; + if (!fstring || fstring[0] == 0) return; - p1275_cmd("interpret", P1275_ARG(0, P1275_ARG_IN_STRING) | - P1275_INOUT(1, 1), fstring); + args[0] = (unsigned long) "interpret"; + args[1] = 1; + args[2] = 1; + args[3] = (unsigned long) fstring; + args[4] = (unsigned long) -1; + + p1275_cmd_direct(args); } EXPORT_SYMBOL(prom_feval); @@ -68,6 +92,7 @@ extern void smp_release(void); */ void prom_cmdline(void) { + unsigned long args[3]; unsigned long flags; local_irq_save(flags); @@ -76,7 +101,11 @@ void prom_cmdline(void) smp_capture(); #endif - p1275_cmd("enter", P1275_INOUT(0, 0)); + args[0] = (unsigned long) "enter"; + args[1] = 0; + args[2] = 0; + + p1275_cmd_direct(args); #ifdef CONFIG_SMP smp_release(); @@ -90,22 +119,32 @@ void prom_cmdline(void) */ void notrace prom_halt(void) { + unsigned long args[3]; + #ifdef CONFIG_SUN_LDOMS if (ldom_domaining_enabled) ldom_power_off(); #endif again: - p1275_cmd("exit", P1275_INOUT(0, 0)); + args[0] = (unsigned long) "exit"; + args[1] = 0; + args[2] = 0; + p1275_cmd_direct(args); goto again; /* PROM is out to get me -DaveM */ } void prom_halt_power_off(void) { + unsigned long args[3]; + #ifdef CONFIG_SUN_LDOMS if (ldom_domaining_enabled) ldom_power_off(); #endif - p1275_cmd("SUNW,power-off", P1275_INOUT(0, 0)); + args[0] = (unsigned long) "SUNW,power-off"; + args[1] = 0; + args[2] = 0; + p1275_cmd_direct(args); /* if nothing else helps, we just halt */ prom_halt(); @@ -114,10 +153,15 @@ void prom_halt_power_off(void) /* Set prom sync handler to call function 'funcp'. */ void prom_setcallback(callback_func_t funcp) { + unsigned long args[5]; if (!funcp) return; - p1275_cmd("set-callback", P1275_ARG(0, P1275_ARG_IN_FUNCTION) | - P1275_INOUT(1, 1), funcp); + args[0] = (unsigned long) "set-callback"; + args[1] = 1; + args[2] = 1; + args[3] = (unsigned long) funcp; + args[4] = (unsigned long) -1; + p1275_cmd_direct(args); } /* Get the idprom and stuff it into buffer 'idbuf'. Returns the @@ -173,57 +217,61 @@ static int prom_get_memory_ihandle(void) } /* Load explicit I/D TLB entries. */ +static long tlb_load(const char *type, unsigned long index, + unsigned long tte_data, unsigned long vaddr) +{ + unsigned long args[9]; + + args[0] = (unsigned long) prom_callmethod_name; + args[1] = 5; + args[2] = 1; + args[3] = (unsigned long) type; + args[4] = (unsigned int) prom_get_mmu_ihandle(); + args[5] = vaddr; + args[6] = tte_data; + args[7] = index; + args[8] = (unsigned long) -1; + + p1275_cmd_direct(args); + + return (long) args[8]; +} + long prom_itlb_load(unsigned long index, unsigned long tte_data, unsigned long vaddr) { - return p1275_cmd(prom_callmethod_name, - (P1275_ARG(0, P1275_ARG_IN_STRING) | - P1275_ARG(2, P1275_ARG_IN_64B) | - P1275_ARG(3, P1275_ARG_IN_64B) | - P1275_INOUT(5, 1)), - "SUNW,itlb-load", - prom_get_mmu_ihandle(), - /* And then our actual args are pushed backwards. */ - vaddr, - tte_data, - index); + return tlb_load("SUNW,itlb-load", index, tte_data, vaddr); } long prom_dtlb_load(unsigned long index, unsigned long tte_data, unsigned long vaddr) { - return p1275_cmd(prom_callmethod_name, - (P1275_ARG(0, P1275_ARG_IN_STRING) | - P1275_ARG(2, P1275_ARG_IN_64B) | - P1275_ARG(3, P1275_ARG_IN_64B) | - P1275_INOUT(5, 1)), - "SUNW,dtlb-load", - prom_get_mmu_ihandle(), - /* And then our actual args are pushed backwards. */ - vaddr, - tte_data, - index); + return tlb_load("SUNW,dtlb-load", index, tte_data, vaddr); } int prom_map(int mode, unsigned long size, unsigned long vaddr, unsigned long paddr) { - int ret = p1275_cmd(prom_callmethod_name, - (P1275_ARG(0, P1275_ARG_IN_STRING) | - P1275_ARG(3, P1275_ARG_IN_64B) | - P1275_ARG(4, P1275_ARG_IN_64B) | - P1275_ARG(6, P1275_ARG_IN_64B) | - P1275_INOUT(7, 1)), - prom_map_name, - prom_get_mmu_ihandle(), - mode, - size, - vaddr, - 0, - paddr); - + unsigned long args[11]; + int ret; + + args[0] = (unsigned long) prom_callmethod_name; + args[1] = 7; + args[2] = 1; + args[3] = (unsigned long) prom_map_name; + args[4] = (unsigned int) prom_get_mmu_ihandle(); + args[5] = (unsigned int) mode; + args[6] = size; + args[7] = vaddr; + args[8] = 0; + args[9] = paddr; + args[10] = (unsigned long) -1; + + p1275_cmd_direct(args); + + ret = (int) args[10]; if (ret == 0) ret = -1; return ret; @@ -231,40 +279,51 @@ int prom_map(int mode, unsigned long size, void prom_unmap(unsigned long size, unsigned long vaddr) { - p1275_cmd(prom_callmethod_name, - (P1275_ARG(0, P1275_ARG_IN_STRING) | - P1275_ARG(2, P1275_ARG_IN_64B) | - P1275_ARG(3, P1275_ARG_IN_64B) | - P1275_INOUT(4, 0)), - prom_unmap_name, - prom_get_mmu_ihandle(), - size, - vaddr); + unsigned long args[7]; + + args[0] = (unsigned long) prom_callmethod_name; + args[1] = 4; + args[2] = 0; + args[3] = (unsigned long) prom_unmap_name; + args[4] = (unsigned int) prom_get_mmu_ihandle(); + args[5] = size; + args[6] = vaddr; + + p1275_cmd_direct(args); } /* Set aside physical memory which is not touched or modified * across soft resets. */ -unsigned long prom_retain(const char *name, - unsigned long pa_low, unsigned long pa_high, - long size, long align) +int prom_retain(const char *name, unsigned long size, + unsigned long align, unsigned long *paddr) { - /* XXX I don't think we return multiple values correctly. - * XXX OBP supposedly returns pa_low/pa_high here, how does - * XXX it work? + unsigned long args[11]; + + args[0] = (unsigned long) prom_callmethod_name; + args[1] = 5; + args[2] = 3; + args[3] = (unsigned long) "SUNW,retain"; + args[4] = (unsigned int) prom_get_memory_ihandle(); + args[5] = align; + args[6] = size; + args[7] = (unsigned long) name; + args[8] = (unsigned long) -1; + args[9] = (unsigned long) -1; + args[10] = (unsigned long) -1; + + p1275_cmd_direct(args); + + if (args[8]) + return (int) args[8]; + + /* Next we get "phys_high" then "phys_low". On 64-bit + * the phys_high cell is don't care since the phys_low + * cell has the full value. */ + *paddr = args[10]; - /* If align is zero, the pa_low/pa_high args are passed, - * else they are not. - */ - if (align == 0) - return p1275_cmd("SUNW,retain", - (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(5, 2)), - name, pa_low, pa_high, size, align); - else - return p1275_cmd("SUNW,retain", - (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(3, 2)), - name, size, align); + return 0; } /* Get "Unumber" string for the SIMM at the given @@ -277,62 +336,129 @@ int prom_getunumber(int syndrome_code, unsigned long phys_addr, char *buf, int buflen) { - return p1275_cmd(prom_callmethod_name, - (P1275_ARG(0, P1275_ARG_IN_STRING) | - P1275_ARG(3, P1275_ARG_OUT_BUF) | - P1275_ARG(6, P1275_ARG_IN_64B) | - P1275_INOUT(8, 2)), - "SUNW,get-unumber", prom_get_memory_ihandle(), - buflen, buf, P1275_SIZE(buflen), - 0, phys_addr, syndrome_code); + unsigned long args[12]; + + args[0] = (unsigned long) prom_callmethod_name; + args[1] = 7; + args[2] = 2; + args[3] = (unsigned long) "SUNW,get-unumber"; + args[4] = (unsigned int) prom_get_memory_ihandle(); + args[5] = buflen; + args[6] = (unsigned long) buf; + args[7] = 0; + args[8] = phys_addr; + args[9] = (unsigned int) syndrome_code; + args[10] = (unsigned long) -1; + args[11] = (unsigned long) -1; + + p1275_cmd_direct(args); + + return (int) args[10]; } /* Power management extensions. */ void prom_sleepself(void) { - p1275_cmd("SUNW,sleep-self", P1275_INOUT(0, 0)); + unsigned long args[3]; + + args[0] = (unsigned long) "SUNW,sleep-self"; + args[1] = 0; + args[2] = 0; + p1275_cmd_direct(args); } int prom_sleepsystem(void) { - return p1275_cmd("SUNW,sleep-system", P1275_INOUT(0, 1)); + unsigned long args[4]; + + args[0] = (unsigned long) "SUNW,sleep-system"; + args[1] = 0; + args[2] = 1; + args[3] = (unsigned long) -1; + p1275_cmd_direct(args); + + return (int) args[3]; } int prom_wakeupsystem(void) { - return p1275_cmd("SUNW,wakeup-system", P1275_INOUT(0, 1)); + unsigned long args[4]; + + args[0] = (unsigned long) "SUNW,wakeup-system"; + args[1] = 0; + args[2] = 1; + args[3] = (unsigned long) -1; + p1275_cmd_direct(args); + + return (int) args[3]; } #ifdef CONFIG_SMP void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg) { - p1275_cmd("SUNW,start-cpu", P1275_INOUT(3, 0), cpunode, pc, arg); + unsigned long args[6]; + + args[0] = (unsigned long) "SUNW,start-cpu"; + args[1] = 3; + args[2] = 0; + args[3] = (unsigned int) cpunode; + args[4] = pc; + args[5] = arg; + p1275_cmd_direct(args); } void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg) { - p1275_cmd("SUNW,start-cpu-by-cpuid", P1275_INOUT(3, 0), - cpuid, pc, arg); + unsigned long args[6]; + + args[0] = (unsigned long) "SUNW,start-cpu-by-cpuid"; + args[1] = 3; + args[2] = 0; + args[3] = (unsigned int) cpuid; + args[4] = pc; + args[5] = arg; + p1275_cmd_direct(args); } void prom_stopcpu_cpuid(int cpuid) { - p1275_cmd("SUNW,stop-cpu-by-cpuid", P1275_INOUT(1, 0), - cpuid); + unsigned long args[4]; + + args[0] = (unsigned long) "SUNW,stop-cpu-by-cpuid"; + args[1] = 1; + args[2] = 0; + args[3] = (unsigned int) cpuid; + p1275_cmd_direct(args); } void prom_stopself(void) { - p1275_cmd("SUNW,stop-self", P1275_INOUT(0, 0)); + unsigned long args[3]; + + args[0] = (unsigned long) "SUNW,stop-self"; + args[1] = 0; + args[2] = 0; + p1275_cmd_direct(args); } void prom_idleself(void) { - p1275_cmd("SUNW,idle-self", P1275_INOUT(0, 0)); + unsigned long args[3]; + + args[0] = (unsigned long) "SUNW,idle-self"; + args[1] = 0; + args[2] = 0; + p1275_cmd_direct(args); } void prom_resumecpu(int cpunode) { - p1275_cmd("SUNW,resume-cpu", P1275_INOUT(1, 0), cpunode); + unsigned long args[4]; + + args[0] = (unsigned long) "SUNW,resume-cpu"; + args[1] = 1; + args[2] = 0; + args[3] = (unsigned int) cpunode; + p1275_cmd_direct(args); } #endif diff --git a/arch/sparc/prom/p1275.c b/arch/sparc/prom/p1275.c index 2d8b70d397f1..fa6e4e219b9c 100644 --- a/arch/sparc/prom/p1275.c +++ b/arch/sparc/prom/p1275.c @@ -22,13 +22,11 @@ struct { long prom_callback; /* 0x00 */ void (*prom_cif_handler)(long *); /* 0x08 */ unsigned long prom_cif_stack; /* 0x10 */ - unsigned long prom_args [23]; /* 0x18 */ - char prom_buffer [3000]; } p1275buf; extern void prom_world(int); -extern void prom_cif_interface(void); +extern void prom_cif_direct(unsigned long *args); extern void prom_cif_callback(void); /* @@ -36,114 +34,20 @@ extern void prom_cif_callback(void); */ DEFINE_RAW_SPINLOCK(prom_entry_lock); -long p1275_cmd(const char *service, long fmt, ...) +void p1275_cmd_direct(unsigned long *args) { - char *p, *q; unsigned long flags; - int nargs, nrets, i; - va_list list; - long attrs, x; - - p = p1275buf.prom_buffer; raw_local_save_flags(flags); raw_local_irq_restore(PIL_NMI); raw_spin_lock(&prom_entry_lock); - p1275buf.prom_args[0] = (unsigned long)p; /* service */ - strcpy (p, service); - p = (char *)(((long)(strchr (p, 0) + 8)) & ~7); - p1275buf.prom_args[1] = nargs = (fmt & 0x0f); /* nargs */ - p1275buf.prom_args[2] = nrets = ((fmt & 0xf0) >> 4); /* nrets */ - attrs = fmt >> 8; - va_start(list, fmt); - for (i = 0; i < nargs; i++, attrs >>= 3) { - switch (attrs & 0x7) { - case P1275_ARG_NUMBER: - p1275buf.prom_args[i + 3] = - (unsigned)va_arg(list, long); - break; - case P1275_ARG_IN_64B: - p1275buf.prom_args[i + 3] = - va_arg(list, unsigned long); - break; - case P1275_ARG_IN_STRING: - strcpy (p, va_arg(list, char *)); - p1275buf.prom_args[i + 3] = (unsigned long)p; - p = (char *)(((long)(strchr (p, 0) + 8)) & ~7); - break; - case P1275_ARG_OUT_BUF: - (void) va_arg(list, char *); - p1275buf.prom_args[i + 3] = (unsigned long)p; - x = va_arg(list, long); - i++; attrs >>= 3; - p = (char *)(((long)(p + (int)x + 7)) & ~7); - p1275buf.prom_args[i + 3] = x; - break; - case P1275_ARG_IN_BUF: - q = va_arg(list, char *); - p1275buf.prom_args[i + 3] = (unsigned long)p; - x = va_arg(list, long); - i++; attrs >>= 3; - memcpy (p, q, (int)x); - p = (char *)(((long)(p + (int)x + 7)) & ~7); - p1275buf.prom_args[i + 3] = x; - break; - case P1275_ARG_OUT_32B: - (void) va_arg(list, char *); - p1275buf.prom_args[i + 3] = (unsigned long)p; - p += 32; - break; - case P1275_ARG_IN_FUNCTION: - p1275buf.prom_args[i + 3] = - (unsigned long)prom_cif_callback; - p1275buf.prom_callback = va_arg(list, long); - break; - } - } - va_end(list); - prom_world(1); - prom_cif_interface(); + prom_cif_direct(args); prom_world(0); - attrs = fmt >> 8; - va_start(list, fmt); - for (i = 0; i < nargs; i++, attrs >>= 3) { - switch (attrs & 0x7) { - case P1275_ARG_NUMBER: - (void) va_arg(list, long); - break; - case P1275_ARG_IN_STRING: - (void) va_arg(list, char *); - break; - case P1275_ARG_IN_FUNCTION: - (void) va_arg(list, long); - break; - case P1275_ARG_IN_BUF: - (void) va_arg(list, char *); - (void) va_arg(list, long); - i++; attrs >>= 3; - break; - case P1275_ARG_OUT_BUF: - p = va_arg(list, char *); - x = va_arg(list, long); - memcpy (p, (char *)(p1275buf.prom_args[i + 3]), (int)x); - i++; attrs >>= 3; - break; - case P1275_ARG_OUT_32B: - p = va_arg(list, char *); - memcpy (p, (char *)(p1275buf.prom_args[i + 3]), 32); - break; - } - } - va_end(list); - x = p1275buf.prom_args [nargs + 3]; - raw_spin_unlock(&prom_entry_lock); raw_local_irq_restore(flags); - - return x; } void prom_cif_init(void *cif_handler, void *cif_stack) diff --git a/arch/sparc/prom/tree_64.c b/arch/sparc/prom/tree_64.c index 3c0d2dd9f693..9d3f9137a43a 100644 --- a/arch/sparc/prom/tree_64.c +++ b/arch/sparc/prom/tree_64.c @@ -16,22 +16,39 @@ #include #include +static int prom_node_to_node(const char *type, int node) +{ + unsigned long args[5]; + + args[0] = (unsigned long) type; + args[1] = 1; + args[2] = 1; + args[3] = (unsigned int) node; + args[4] = (unsigned long) -1; + + p1275_cmd_direct(args); + + return (int) args[4]; +} + /* Return the child of node 'node' or zero if no this node has no * direct descendent. */ inline int __prom_getchild(int node) { - return p1275_cmd ("child", P1275_INOUT(1, 1), node); + return prom_node_to_node("child", node); } inline int prom_getchild(int node) { int cnode; - if(node == -1) return 0; + if (node == -1) + return 0; cnode = __prom_getchild(node); - if(cnode == -1) return 0; - return (int)cnode; + if (cnode == -1) + return 0; + return cnode; } EXPORT_SYMBOL(prom_getchild); @@ -39,10 +56,12 @@ inline int prom_getparent(int node) { int cnode; - if(node == -1) return 0; - cnode = p1275_cmd ("parent", P1275_INOUT(1, 1), node); - if(cnode == -1) return 0; - return (int)cnode; + if (node == -1) + return 0; + cnode = prom_node_to_node("parent", node); + if (cnode == -1) + return 0; + return cnode; } /* Return the next sibling of node 'node' or zero if no more siblings @@ -50,7 +69,7 @@ inline int prom_getparent(int node) */ inline int __prom_getsibling(int node) { - return p1275_cmd(prom_peer_name, P1275_INOUT(1, 1), node); + return prom_node_to_node(prom_peer_name, node); } inline int prom_getsibling(int node) @@ -72,11 +91,21 @@ EXPORT_SYMBOL(prom_getsibling); */ inline int prom_getproplen(int node, const char *prop) { - if((!node) || (!prop)) return -1; - return p1275_cmd ("getproplen", - P1275_ARG(1,P1275_ARG_IN_STRING)| - P1275_INOUT(2, 1), - node, prop); + unsigned long args[6]; + + if (!node || !prop) + return -1; + + args[0] = (unsigned long) "getproplen"; + args[1] = 2; + args[2] = 1; + args[3] = (unsigned int) node; + args[4] = (unsigned long) prop; + args[5] = (unsigned long) -1; + + p1275_cmd_direct(args); + + return (int) args[5]; } EXPORT_SYMBOL(prom_getproplen); @@ -87,19 +116,25 @@ EXPORT_SYMBOL(prom_getproplen); inline int prom_getproperty(int node, const char *prop, char *buffer, int bufsize) { + unsigned long args[8]; int plen; plen = prom_getproplen(node, prop); - if ((plen > bufsize) || (plen == 0) || (plen == -1)) { + if ((plen > bufsize) || (plen == 0) || (plen == -1)) return -1; - } else { - /* Ok, things seem all right. */ - return p1275_cmd(prom_getprop_name, - P1275_ARG(1,P1275_ARG_IN_STRING)| - P1275_ARG(2,P1275_ARG_OUT_BUF)| - P1275_INOUT(4, 1), - node, prop, buffer, P1275_SIZE(plen)); - } + + args[0] = (unsigned long) prom_getprop_name; + args[1] = 4; + args[2] = 1; + args[3] = (unsigned int) node; + args[4] = (unsigned long) prop; + args[5] = (unsigned long) buffer; + args[6] = bufsize; + args[7] = (unsigned long) -1; + + p1275_cmd_direct(args); + + return (int) args[7]; } EXPORT_SYMBOL(prom_getproperty); @@ -110,7 +145,7 @@ inline int prom_getint(int node, const char *prop) { int intprop; - if(prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1) + if (prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1) return intprop; return -1; @@ -126,7 +161,8 @@ int prom_getintdefault(int node, const char *property, int deflt) int retval; retval = prom_getint(node, property); - if(retval == -1) return deflt; + if (retval == -1) + return deflt; return retval; } @@ -138,7 +174,8 @@ int prom_getbool(int node, const char *prop) int retval; retval = prom_getproplen(node, prop); - if(retval == -1) return 0; + if (retval == -1) + return 0; return 1; } EXPORT_SYMBOL(prom_getbool); @@ -152,7 +189,8 @@ void prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size) int len; len = prom_getproperty(node, prop, user_buf, ubuf_size); - if(len != -1) return; + if (len != -1) + return; user_buf[0] = 0; } EXPORT_SYMBOL(prom_getstring); @@ -164,7 +202,8 @@ int prom_nodematch(int node, const char *name) { char namebuf[128]; prom_getproperty(node, "name", namebuf, sizeof(namebuf)); - if(strcmp(namebuf, name) == 0) return 1; + if (strcmp(namebuf, name) == 0) + return 1; return 0; } @@ -190,16 +229,29 @@ int prom_searchsiblings(int node_start, const char *nodename) } EXPORT_SYMBOL(prom_searchsiblings); +static const char *prom_nextprop_name = "nextprop"; + /* Return the first property type for node 'node'. * buffer should be at least 32B in length */ inline char *prom_firstprop(int node, char *buffer) { + unsigned long args[7]; + *buffer = 0; - if(node == -1) return buffer; - p1275_cmd ("nextprop", P1275_ARG(2,P1275_ARG_OUT_32B)| - P1275_INOUT(3, 0), - node, (char *) 0x0, buffer); + if (node == -1) + return buffer; + + args[0] = (unsigned long) prom_nextprop_name; + args[1] = 3; + args[2] = 1; + args[3] = (unsigned int) node; + args[4] = 0; + args[5] = (unsigned long) buffer; + args[6] = (unsigned long) -1; + + p1275_cmd_direct(args); + return buffer; } EXPORT_SYMBOL(prom_firstprop); @@ -210,9 +262,10 @@ EXPORT_SYMBOL(prom_firstprop); */ inline char *prom_nextprop(int node, const char *oprop, char *buffer) { + unsigned long args[7]; char buf[32]; - if(node == -1) { + if (node == -1) { *buffer = 0; return buffer; } @@ -220,10 +273,17 @@ inline char *prom_nextprop(int node, const char *oprop, char *buffer) strcpy (buf, oprop); oprop = buf; } - p1275_cmd ("nextprop", P1275_ARG(1,P1275_ARG_IN_STRING)| - P1275_ARG(2,P1275_ARG_OUT_32B)| - P1275_INOUT(3, 0), - node, oprop, buffer); + + args[0] = (unsigned long) prom_nextprop_name; + args[1] = 3; + args[2] = 1; + args[3] = (unsigned int) node; + args[4] = (unsigned long) oprop; + args[5] = (unsigned long) buffer; + args[6] = (unsigned long) -1; + + p1275_cmd_direct(args); + return buffer; } EXPORT_SYMBOL(prom_nextprop); @@ -231,12 +291,19 @@ EXPORT_SYMBOL(prom_nextprop); int prom_finddevice(const char *name) { + unsigned long args[5]; + if (!name) return 0; - return p1275_cmd(prom_finddev_name, - P1275_ARG(0,P1275_ARG_IN_STRING)| - P1275_INOUT(1, 1), - name); + args[0] = (unsigned long) "finddevice"; + args[1] = 1; + args[2] = 1; + args[3] = (unsigned long) name; + args[4] = (unsigned long) -1; + + p1275_cmd_direct(args); + + return (int) args[4]; } EXPORT_SYMBOL(prom_finddevice); @@ -247,7 +314,7 @@ int prom_node_has_property(int node, const char *prop) *buf = 0; do { prom_nextprop(node, buf, buf); - if(!strcmp(buf, prop)) + if (!strcmp(buf, prop)) return 1; } while (*buf); return 0; @@ -260,6 +327,8 @@ EXPORT_SYMBOL(prom_node_has_property); int prom_setprop(int node, const char *pname, char *value, int size) { + unsigned long args[8]; + if (size == 0) return 0; if ((pname == 0) || (value == 0)) @@ -271,19 +340,37 @@ prom_setprop(int node, const char *pname, char *value, int size) return 0; } #endif - return p1275_cmd ("setprop", P1275_ARG(1,P1275_ARG_IN_STRING)| - P1275_ARG(2,P1275_ARG_IN_BUF)| - P1275_INOUT(4, 1), - node, pname, value, P1275_SIZE(size)); + args[0] = (unsigned long) "setprop"; + args[1] = 4; + args[2] = 1; + args[3] = (unsigned int) node; + args[4] = (unsigned long) pname; + args[5] = (unsigned long) value; + args[6] = size; + args[7] = (unsigned long) -1; + + p1275_cmd_direct(args); + + return (int) args[7]; } EXPORT_SYMBOL(prom_setprop); inline int prom_inst2pkg(int inst) { + unsigned long args[5]; int node; - node = p1275_cmd ("instance-to-package", P1275_INOUT(1, 1), inst); - if (node == -1) return 0; + args[0] = (unsigned long) "instance-to-package"; + args[1] = 1; + args[2] = 1; + args[3] = (unsigned int) inst; + args[4] = (unsigned long) -1; + + p1275_cmd_direct(args); + + node = (int) args[4]; + if (node == -1) + return 0; return node; } @@ -296,17 +383,28 @@ prom_pathtoinode(const char *path) int node, inst; inst = prom_devopen (path); - if (inst == 0) return 0; - node = prom_inst2pkg (inst); - prom_devclose (inst); - if (node == -1) return 0; + if (inst == 0) + return 0; + node = prom_inst2pkg(inst); + prom_devclose(inst); + if (node == -1) + return 0; return node; } int prom_ihandle2path(int handle, char *buffer, int bufsize) { - return p1275_cmd("instance-to-path", - P1275_ARG(1,P1275_ARG_OUT_BUF)| - P1275_INOUT(3, 1), - handle, buffer, P1275_SIZE(bufsize)); + unsigned long args[7]; + + args[0] = (unsigned long) "instance-to-path"; + args[1] = 3; + args[2] = 1; + args[3] = (unsigned int) handle; + args[4] = (unsigned long) buffer; + args[5] = bufsize; + args[6] = (unsigned long) -1; + + p1275_cmd_direct(args); + + return (int) args[6]; } -- cgit v1.2.3 From 9df2a1a9348fe1098e55ca3899963a60419c12d8 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 15 Sep 2010 11:43:28 +0000 Subject: drivers/net/usb/hso.c: prevent reading uninitialized memory commit 7011e660938fc44ed86319c18a5954e95a82ab3e upstream. Fixed formatting (tabs and line breaks). The TIOCGICOUNT device ioctl allows unprivileged users to read uninitialized stack memory, because the "reserved" member of the serial_icounter_struct struct declared on the stack in hso_get_count() is not altered or zeroed before being copied back to the user. This patch takes care of it. Signed-off-by: Dan Rosenberg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/hso.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 4dd23513c5af..e2542742261f 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1653,6 +1653,8 @@ static int hso_get_count(struct hso_serial *serial, struct uart_icount cnow; struct hso_tiocmget *tiocmget = serial->tiocmget; + memset(&icount, 0, sizeof(struct serial_icounter_struct)); + if (!tiocmget) return -ENOENT; spin_lock_irq(&serial->serial_lock); -- cgit v1.2.3 From 79872c1916caaebb002448f63455050cfde581cf Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 15 Sep 2010 11:43:12 +0000 Subject: drivers/net/cxgb3/cxgb3_main.c: prevent reading uninitialized stack memory commit 49c37c0334a9b85d30ab3d6b5d1acb05ef2ef6de upstream. Fixed formatting (tabs and line breaks). The CHELSIO_GET_QSET_NUM device ioctl allows unprivileged users to read 4 bytes of uninitialized stack memory, because the "addr" member of the ch_reg struct declared on the stack in cxgb_extension_ioctl() is not altered or zeroed before being copied back to the user. This patch takes care of it. Signed-off-by: Dan Rosenberg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/cxgb3/cxgb3_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index e3f1b8566495..3e0f19f75c82 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -2296,6 +2296,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) case CHELSIO_GET_QSET_NUM:{ struct ch_reg edata; + memset(&edata, 0, sizeof(struct ch_reg)); + edata.cmd = CHELSIO_GET_QSET_NUM; edata.val = pi->nqsets; if (copy_to_user(useraddr, &edata, sizeof(edata))) -- cgit v1.2.3 From 073b0b42c9a06e8c3d2e81fac440e3f387c0498a Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 15 Sep 2010 11:43:04 +0000 Subject: drivers/net/eql.c: prevent reading uninitialized stack memory commit 44467187dc22fdd33a1a06ea0ba86ce20be3fe3c upstream. Fixed formatting (tabs and line breaks). The EQL_GETMASTRCFG device ioctl allows unprivileged users to read 16 bytes of uninitialized stack memory, because the "master_name" member of the master_config_t struct declared on the stack in eql_g_master_cfg() is not altered or zeroed before being copied back to the user. This patch takes care of it. Signed-off-by: Dan Rosenberg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/eql.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/eql.c b/drivers/net/eql.c index dda2c7944da9..0cb1cf9cf4b0 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c @@ -555,6 +555,8 @@ static int eql_g_master_cfg(struct net_device *dev, master_config_t __user *mcp) equalizer_t *eql; master_config_t mc; + memset(&mc, 0, sizeof(master_config_t)); + if (eql_is_master(dev)) { eql = netdev_priv(dev); mc.max_slaves = eql->max_slaves; -- cgit v1.2.3 From b38ac5ef17532d9d73dc08859fd256a647e969db Mon Sep 17 00:00:00 2001 From: Andy Gospodarek Date: Fri, 10 Sep 2010 11:43:20 +0000 Subject: bonding: correctly process non-linear skbs commit ab12811c89e88f2e66746790b1fe4469ccb7bdd9 upstream. It was recently brought to my attention that 802.3ad mode bonds would no longer form when using some network hardware after a driver update. After snooping around I realized that the particular hardware was using page-based skbs and found that skb->data did not contain a valid LACPDU as it was not stored there. That explained the inability to form an 802.3ad-based bond. For balance-alb mode bonds this was also an issue as ARPs would not be properly processed. This patch fixes the issue in my tests and should be applied to 2.6.36 and as far back as anyone cares to add it to stable. Thanks to Alexander Duyck and Jesse Brandeburg for the suggestions on this one. Signed-off-by: Andy Gospodarek CC: Alexander Duyck CC: Jesse Brandeburg Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/bonding/bond_3ad.c | 3 +++ drivers/net/bonding/bond_alb.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 822f586d72af..0ddf4c66afe2 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2466,6 +2466,9 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac if (!(dev->flags & IFF_MASTER)) goto out; + if (!pskb_may_pull(skb, sizeof(struct lacpdu))) + goto out; + read_lock(&bond->lock); slave = bond_get_slave_by_dev((struct bonding *)netdev_priv(dev), orig_dev); diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 8d7dfd2f1e90..0cb1ded1bf89 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -369,6 +369,9 @@ static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct goto out; } + if (!pskb_may_pull(skb, arp_hdr_len(bond_dev))) + goto out; + if (skb->len < sizeof(struct arp_pkt)) { pr_debug("Packet is too small to be an ARP\n"); goto out; -- cgit v1.2.3 From 9db783be92c6c07d4ff6238d01022368a29e0d82 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 6 Sep 2010 14:32:30 +0200 Subject: Staging: vt6655: fix buffer overflow commit dd173abfead903c7df54e977535973f3312cd307 upstream. "param->u.wpa_associate.wpa_ie_len" comes from the user. We should check it so that the copy_from_user() doesn't overflow the buffer. Also further down in the function, we assume that if "param->u.wpa_associate.wpa_ie_len" is set then "abyWPAIE[0]" is initialized. To make that work, I changed the test here to say that if "wpa_ie_len" is set then "wpa_ie" has to be a valid pointer or we return -EINVAL. Oddly, we only use the first element of the abyWPAIE[] array. So I suspect there may be some other issues in this function. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/wpactl.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c index 22c2fab3f328..f79808ee51b3 100644 --- a/drivers/staging/vt6655/wpactl.c +++ b/drivers/staging/vt6655/wpactl.c @@ -766,9 +766,14 @@ static int wpa_set_associate(PSDevice pDevice, DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len); - if (param->u.wpa_associate.wpa_ie && - copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len)) - return -EINVAL; + if (param->u.wpa_associate.wpa_ie_len) { + if (!param->u.wpa_associate.wpa_ie) + return -EINVAL; + if (param->u.wpa_associate.wpa_ie_len > sizeof(abyWPAIE)) + return -EINVAL; + if (copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len)) + return -EFAULT; + } if (param->u.wpa_associate.mode == 1) pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA; -- cgit v1.2.3 From 5b11eef8e3d3e3b2ce9aae50f6ab4fd8451cfc5b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 10 Sep 2010 01:56:16 +0000 Subject: net/llc: make opt unsigned in llc_ui_setsockopt() commit 339db11b219f36cf7da61b390992d95bb6b7ba2e upstream. The members of struct llc_sock are unsigned so if we pass a negative value for "opt" it can cause a sign bug. Also it can cause an integer overflow when we multiply "opt * HZ". Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/llc/af_llc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 023ba820236f..582612998211 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -1024,7 +1024,8 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname, { struct sock *sk = sock->sk; struct llc_sock *llc = llc_sk(sk); - int rc = -EINVAL, opt; + unsigned int opt; + int rc = -EINVAL; lock_sock(sk); if (unlikely(level != SOL_LLC || optlen != sizeof(int))) -- cgit v1.2.3 From 69bce8b48bc106ee22e68013dcfdbda8ed45f1ac Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Thu, 9 Sep 2010 16:37:52 -0700 Subject: mm: fix swapin race condition commit 4969c1192d15afa3389e7ae3302096ff684ba655 upstream. The pte_same check is reliable only if the swap entry remains pinned (by the page lock on swapcache). We've also to ensure the swapcache isn't removed before we take the lock as try_to_free_swap won't care about the page pin. One of the possible impacts of this patch is that a KSM-shared page can point to the anon_vma of another process, which could exit before the page is freed. This can leave a page with a pointer to a recycled anon_vma object, or worse, a pointer to something that is no longer an anon_vma. [Backport to 2.6.35.5 (anon_vma instead of anon_vma->root in ksm.h) by Hugh] [riel@redhat.com: changelog help] Signed-off-by: Andrea Arcangeli Acked-by: Hugh Dickins Reviewed-by: Rik van Riel Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Hugh Dickins Signed-off-by: Greg Kroah-Hartman --- include/linux/ksm.h | 20 +++++++++----------- mm/ksm.c | 3 --- mm/memory.c | 39 ++++++++++++++++++++++++++++++++++----- 3 files changed, 43 insertions(+), 19 deletions(-) diff --git a/include/linux/ksm.h b/include/linux/ksm.h index 43bdab769fc3..e809eb1a35d1 100644 --- a/include/linux/ksm.h +++ b/include/linux/ksm.h @@ -16,6 +16,9 @@ struct stable_node; struct mem_cgroup; +struct page *ksm_does_need_to_copy(struct page *page, + struct vm_area_struct *vma, unsigned long address); + #ifdef CONFIG_KSM int ksm_madvise(struct vm_area_struct *vma, unsigned long start, unsigned long end, int advice, unsigned long *vm_flags); @@ -70,19 +73,14 @@ static inline void set_page_stable_node(struct page *page, * We'd like to make this conditional on vma->vm_flags & VM_MERGEABLE, * but what if the vma was unmerged while the page was swapped out? */ -struct page *ksm_does_need_to_copy(struct page *page, - struct vm_area_struct *vma, unsigned long address); -static inline struct page *ksm_might_need_to_copy(struct page *page, +static inline int ksm_might_need_to_copy(struct page *page, struct vm_area_struct *vma, unsigned long address) { struct anon_vma *anon_vma = page_anon_vma(page); - if (!anon_vma || - (anon_vma == vma->anon_vma && - page->index == linear_page_index(vma, address))) - return page; - - return ksm_does_need_to_copy(page, vma, address); + return anon_vma && + (anon_vma != vma->anon_vma || + page->index != linear_page_index(vma, address)); } int page_referenced_ksm(struct page *page, @@ -115,10 +113,10 @@ static inline int ksm_madvise(struct vm_area_struct *vma, unsigned long start, return 0; } -static inline struct page *ksm_might_need_to_copy(struct page *page, +static inline int ksm_might_need_to_copy(struct page *page, struct vm_area_struct *vma, unsigned long address) { - return page; + return 0; } static inline int page_referenced_ksm(struct page *page, diff --git a/mm/ksm.c b/mm/ksm.c index 6c3e99b4ae7c..17ee9df378ca 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -1523,8 +1523,6 @@ struct page *ksm_does_need_to_copy(struct page *page, { struct page *new_page; - unlock_page(page); /* any racers will COW it, not modify it */ - new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address); if (new_page) { copy_user_highpage(new_page, page, address, vma); @@ -1540,7 +1538,6 @@ struct page *ksm_does_need_to_copy(struct page *page, add_page_to_unevictable_list(new_page); } - page_cache_release(page); return new_page; } diff --git a/mm/memory.c b/mm/memory.c index 53cf85d44449..608420344784 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2626,7 +2626,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned int flags, pte_t orig_pte) { spinlock_t *ptl; - struct page *page; + struct page *page, *swapcache = NULL; swp_entry_t entry; pte_t pte; struct mem_cgroup *ptr = NULL; @@ -2681,10 +2681,23 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, lock_page(page); delayacct_clear_flag(DELAYACCT_PF_SWAPIN); - page = ksm_might_need_to_copy(page, vma, address); - if (!page) { - ret = VM_FAULT_OOM; - goto out; + /* + * Make sure try_to_free_swap didn't release the swapcache + * from under us. The page pin isn't enough to prevent that. + */ + if (unlikely(!PageSwapCache(page))) + goto out_page; + + if (ksm_might_need_to_copy(page, vma, address)) { + swapcache = page; + page = ksm_does_need_to_copy(page, vma, address); + + if (unlikely(!page)) { + ret = VM_FAULT_OOM; + page = swapcache; + swapcache = NULL; + goto out_page; + } } if (mem_cgroup_try_charge_swapin(mm, page, GFP_KERNEL, &ptr)) { @@ -2735,6 +2748,18 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, if (vm_swap_full() || (vma->vm_flags & VM_LOCKED) || PageMlocked(page)) try_to_free_swap(page); unlock_page(page); + if (swapcache) { + /* + * Hold the lock to avoid the swap entry to be reused + * until we take the PT lock for the pte_same() check + * (to avoid false positives from pte_same). For + * further safety release the lock after the swap_free + * so that the swap count won't change under a + * parallel locked swapcache. + */ + unlock_page(swapcache); + page_cache_release(swapcache); + } if (flags & FAULT_FLAG_WRITE) { ret |= do_wp_page(mm, vma, address, page_table, pmd, ptl, pte); @@ -2756,6 +2781,10 @@ out_page: unlock_page(page); out_release: page_cache_release(page); + if (swapcache) { + unlock_page(swapcache); + page_cache_release(swapcache); + } return ret; } -- cgit v1.2.3 From d987d040e9623502a97a9dd742377d4ec00e2ba2 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Sun, 19 Sep 2010 19:40:22 -0700 Subject: mm: further fix swapin race condition commit 31c4a3d3a0f84a5847665f8aa0552d188389f791 upstream. Commit 4969c1192d15 ("mm: fix swapin race condition") is now agreed to be incomplete. There's a race, not very much less likely than the original race envisaged, in which it is further necessary to check that the swapcache page's swap has not changed. Here's the reasoning: cast in terms of reuse_swap_page(), but probably could be reformulated to rely on try_to_free_swap() instead, or on swapoff+swapon. A, faults into do_swap_page(): does page1 = lookup_swap_cache(swap1) and comes through the lock_page(page1). B, a racing thread of the same process, faults on the same address: does page1 = lookup_swap_cache(swap1) and now waits in lock_page(page1), but for whatever reason is unlucky not to get the lock any time soon. A carries on through do_swap_page(), a write fault, but cannot reuse the swap page1 (another reference to swap1). Unlocks the page1 (but B doesn't get it yet), does COW in do_wp_page(), page2 now in that pte. C, perhaps the parent of A+B, comes in and write faults the same swap page1 into its mm, reuse_swap_page() succeeds this time, swap1 is freed. kswapd comes in after some time (B still unlucky) and swaps out some pages from A+B and C: it allocates the original swap1 to page2 in A+B, and some other swap2 to the original page1 now in C. But does not immediately free page1 (actually it couldn't: B holds a reference), leaving it in swap cache for now. B at last gets the lock on page1, hooray! Is PageSwapCache(page1)? Yes. Is pte_same(*page_table, orig_pte)? Yes, because page2 has now been given the swap1 which page1 used to have. So B proceeds to insert page1 into A+B's page_table, though its content now belongs to C, quite different from what A wrote there. B ought to have checked that page1's swap was still swap1. Signed-off-by: Hugh Dickins Reviewed-by: Rik van Riel Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/memory.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 608420344784..93da8f1338c4 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2682,10 +2682,12 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, delayacct_clear_flag(DELAYACCT_PF_SWAPIN); /* - * Make sure try_to_free_swap didn't release the swapcache - * from under us. The page pin isn't enough to prevent that. + * Make sure try_to_free_swap or reuse_swap_page or swapoff did not + * release the swapcache from under us. The page pin, and pte_same + * test below, are not enough to exclude that. Even if it is still + * swapcache, we need to check that the page's swap has not changed. */ - if (unlikely(!PageSwapCache(page))) + if (unlikely(!PageSwapCache(page) || page_private(page) != entry.val)) goto out_page; if (ksm_might_need_to_copy(page, vma, address)) { -- cgit v1.2.3 From d4f5d4c1a4f45e69deb3bcf727e511b0637a72d1 Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Tue, 14 Sep 2010 13:26:16 +0530 Subject: virtio: console: Prevent userspace from submitting NULL buffers commit 65745422a898741ee0e7068ef06624ab06e8aefa upstream. A userspace could submit a buffer with 0 length to be written to the host. Prevent such a situation. This was not needed previously, but recent changes in the way write() works exposed this condition to trigger a virtqueue event to the host, causing a NULL buffer to be sent across. Signed-off-by: Amit Shah Signed-off-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- drivers/char/virtio_console.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 942a9826bd23..56ffd0d93e25 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -596,6 +596,10 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, ssize_t ret; bool nonblock; + /* Userspace could be out to fool us */ + if (!count) + return 0; + port = filp->private_data; nonblock = filp->f_flags & O_NONBLOCK; -- cgit v1.2.3 From ba4de7fd43bb21be634a39b0de274cfb9b19fd83 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 16 Sep 2010 14:43:08 +0530 Subject: virtio: console: Fix poll blocking even though there is data to read commit 6df7aadcd9290807c464675098b5dd2dc9da5075 upstream. I found this while working on a Linux agent for spice, the symptom I was seeing was select blocking on the spice vdagent virtio serial port even though there were messages queued up there. virtio_console's port_fops_poll checks port->inbuf != NULL to determine if read won't block. However if an application reads enough bytes from inbuf through port_fops_read, to empty the current port->inbuf, port->inbuf will be NULL even though there may be buffers left in the virtqueue. This causes poll() to block even though there is data to be read, this patch fixes this by using will_read_block(port) instead of the port->inbuf != NULL check. Signed-off-By: Hans de Goede Signed-off-by: Amit Shah Signed-off-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- drivers/char/virtio_console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 56ffd0d93e25..c810481a5bc2 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -646,7 +646,7 @@ static unsigned int port_fops_poll(struct file *filp, poll_table *wait) poll_wait(filp, &port->waitqueue, wait); ret = 0; - if (port->inbuf) + if (!will_read_block(port)) ret |= POLLIN | POLLRDNORM; if (!will_write_block(port)) ret |= POLLOUT; -- cgit v1.2.3 From 6d51cdffcae15394f615489d57d8ca0e9a91e494 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Sun, 19 Sep 2010 10:28:52 +0800 Subject: intel_agp, drm/i915: Add all sandybridge graphics devices support New pci ids for all sandybridge graphics versions on desktop/mobile/server. [This is backport patch from upstream commit 4fefe435 and 85540480.] Signed-off-by: Zhenyu Wang Signed-off-by: Greg Kroah-Hartman --- drivers/char/agp/intel-agp.c | 19 +++++++++++++++---- drivers/char/agp/intel-agp.h | 17 ++++++++++++----- drivers/char/agp/intel-gtt.c | 37 +++++++++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/i915_drv.c | 5 +++++ 4 files changed, 67 insertions(+), 11 deletions(-) diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index d836a71bf06d..4874b5b42224 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -815,10 +815,20 @@ static const struct intel_driver_description { "HD Graphics", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, "HD Graphics", NULL, &intel_i965_driver }, - { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG, - "Sandybridge", NULL, &intel_i965_driver }, - { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG, - "Sandybridge", NULL, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG, + "Sandybridge", NULL, &intel_gen6_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG, + "Sandybridge", NULL, &intel_gen6_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG, + "Sandybridge", NULL, &intel_gen6_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG, + "Sandybridge", NULL, &intel_gen6_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG, + "Sandybridge", NULL, &intel_gen6_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG, + "Sandybridge", NULL, &intel_gen6_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG, + "Sandybridge", NULL, &intel_gen6_driver }, { 0, 0, NULL, NULL, NULL } }; @@ -1036,6 +1046,7 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB), ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB), + ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB), { } }; diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index 2547465d4658..ffa87b7ff50f 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -194,10 +194,16 @@ #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG 0x0102 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG 0x0106 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100 /* Desktop */ +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG 0x0102 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG 0x0112 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG 0x0122 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104 /* Mobile */ +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG 0x0106 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG 0x0116 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG 0x0126 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB 0x0108 /* Server */ +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG 0x010A /* cover 915 and 945 variants */ #define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \ @@ -224,7 +230,8 @@ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB) #define IS_SNB (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB) #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index ea6997e3558e..c1119ee08adc 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -585,8 +585,7 @@ static void intel_i830_init_gtt_entries(void) gtt_entries = 0; break; } - } else if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) { + } else if (IS_SNB) { /* * SandyBridge has new memory control reg at 0x50.w */ @@ -1337,6 +1336,7 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) break; case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB: case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB: + case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB: *gtt_offset = MB(2); pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); @@ -1526,6 +1526,39 @@ static const struct agp_bridge_driver intel_i965_driver = { #endif }; +static const struct agp_bridge_driver intel_gen6_driver = { + .owner = THIS_MODULE, + .aperture_sizes = intel_i830_sizes, + .size_type = FIXED_APER_SIZE, + .num_aperture_sizes = 4, + .needs_scratch_page = true, + .configure = intel_i9xx_configure, + .fetch_size = intel_i9xx_fetch_size, + .cleanup = intel_i915_cleanup, + .mask_memory = intel_i965_mask_memory, + .masks = intel_i810_masks, + .agp_enable = intel_i810_agp_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = intel_i965_create_gatt_table, + .free_gatt_table = intel_i830_free_gatt_table, + .insert_memory = intel_i915_insert_entries, + .remove_memory = intel_i915_remove_entries, + .alloc_by_type = intel_i830_alloc_by_type, + .free_by_type = intel_i810_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_alloc_pages = agp_generic_alloc_pages, + .agp_destroy_page = agp_generic_destroy_page, + .agp_destroy_pages = agp_generic_destroy_pages, + .agp_type_to_mask_type = intel_i830_type_to_mask_type, + .chipset_flush = intel_i915_chipset_flush, +#ifdef USE_PCI_DMA_API + .agp_map_page = intel_agp_map_page, + .agp_unmap_page = intel_agp_unmap_page, + .agp_map_memory = intel_agp_map_memory, + .agp_unmap_memory = intel_agp_unmap_memory, +#endif +}; + static const struct agp_bridge_driver intel_g33_driver = { .owner = THIS_MODULE, .aperture_sizes = intel_i830_sizes, diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 423dc90c1e20..07a0cf1e3ab5 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -180,7 +180,12 @@ static const struct pci_device_id pciidlist[] = { INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info), INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info), INTEL_VGA_DEVICE(0x0102, &intel_sandybridge_d_info), + INTEL_VGA_DEVICE(0x0112, &intel_sandybridge_d_info), + INTEL_VGA_DEVICE(0x0122, &intel_sandybridge_d_info), INTEL_VGA_DEVICE(0x0106, &intel_sandybridge_m_info), + INTEL_VGA_DEVICE(0x0116, &intel_sandybridge_m_info), + INTEL_VGA_DEVICE(0x0126, &intel_sandybridge_m_info), + INTEL_VGA_DEVICE(0x010A, &intel_sandybridge_d_info), {0, 0, 0} }; -- cgit v1.2.3 From 1252894fa9ea0a4e73cb68f49f5913dda9834d6c Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Sun, 19 Sep 2010 10:28:53 +0800 Subject: agp/intel: fix physical address mask bits for sandybridge [This is backport patch from upstream 8dfc2b14.] Signed-off-by: Zhenyu Wang Signed-off-by: Greg Kroah-Hartman --- drivers/char/agp/intel-gtt.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index c1119ee08adc..ed11c770c9ab 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1317,6 +1317,16 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, return addr | bridge->driver->masks[type].mask; } +static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge, + dma_addr_t addr, int type) +{ + /* gen6 has bit11-4 for physical addr bit39-32 */ + addr |= (addr >> 28) & 0xff0; + + /* Type checking must be done elsewhere */ + return addr | bridge->driver->masks[type].mask; +} + static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) { u16 snb_gmch_ctl; @@ -1535,7 +1545,7 @@ static const struct agp_bridge_driver intel_gen6_driver = { .configure = intel_i9xx_configure, .fetch_size = intel_i9xx_fetch_size, .cleanup = intel_i915_cleanup, - .mask_memory = intel_i965_mask_memory, + .mask_memory = intel_gen6_mask_memory, .masks = intel_i810_masks, .agp_enable = intel_i810_agp_enable, .cache_flush = global_cache_flush, -- cgit v1.2.3 From 96b6a8c56dbee75f61271f6484f56730beb17a20 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Sun, 19 Sep 2010 10:28:54 +0800 Subject: agp/intel: fix dma mask bits on sandybridge [This is backport patch from upstream 877fdacf.] Signed-off-by: Zhenyu Wang Signed-off-by: Greg Kroah-Hartman --- drivers/char/agp/intel-agp.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 4874b5b42224..fe9c6e0b6179 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -835,7 +835,7 @@ static const struct intel_driver_description { static int __devinit intel_gmch_probe(struct pci_dev *pdev, struct agp_bridge_data *bridge) { - int i; + int i, mask; bridge->driver = NULL; for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { @@ -855,14 +855,19 @@ static int __devinit intel_gmch_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name); - if (bridge->driver->mask_memory == intel_i965_mask_memory) { - if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(36))) - dev_err(&intel_private.pcidev->dev, - "set gfx device dma mask 36bit failed!\n"); - else - pci_set_consistent_dma_mask(intel_private.pcidev, - DMA_BIT_MASK(36)); - } + if (bridge->driver->mask_memory == intel_gen6_mask_memory) + mask = 40; + else if (bridge->driver->mask_memory == intel_i965_mask_memory) + mask = 36; + else + mask = 32; + + if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) + dev_err(&intel_private.pcidev->dev, + "set gfx device dma mask %d-bit failed!\n", mask); + else + pci_set_consistent_dma_mask(intel_private.pcidev, + DMA_BIT_MASK(mask)); return 1; } -- cgit v1.2.3 From e5aec52ddb8d72e0fe2ab17f637e2f4428b19da0 Mon Sep 17 00:00:00 2001 From: Matt Helsley Date: Mon, 13 Sep 2010 13:01:18 -0700 Subject: hw breakpoints: Fix pid namespace bug commit 068e35eee9ef98eb4cab55181977e24995d273be upstream. Hardware breakpoints can't be registered within pid namespaces because tsk->pid is passed rather than the pid in the current namespace. (See https://bugzilla.kernel.org/show_bug.cgi?id=17281 ) This is a quick fix demonstrating the problem but is not the best method of solving the problem since passing pids internally is not the best way to avoid pid namespace bugs. Subsequent patches will show a better solution. Much thanks to Frederic Weisbecker for doing the bulk of the work finding this bug. Reported-by: Robin Green Signed-off-by: Matt Helsley Signed-off-by: Peter Zijlstra Cc: Prasad Cc: Arnaldo Carvalho de Melo Cc: Steven Rostedt Cc: Will Deacon Cc: Mahesh Salgaonkar LKML-Reference: Signed-off-by: Ingo Molnar Signed-off-by: Frederic Weisbecker Signed-off-by: Greg Kroah-Hartman --- kernel/hw_breakpoint.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c index 7a56b22e0602..6eb642219713 100644 --- a/kernel/hw_breakpoint.c +++ b/kernel/hw_breakpoint.c @@ -417,7 +417,8 @@ register_user_hw_breakpoint(struct perf_event_attr *attr, perf_overflow_handler_t triggered, struct task_struct *tsk) { - return perf_event_create_kernel_counter(attr, -1, tsk->pid, triggered); + return perf_event_create_kernel_counter(attr, -1, task_pid_vnr(tsk), + triggered); } EXPORT_SYMBOL_GPL(register_user_hw_breakpoint); -- cgit v1.2.3 From 7495973bc945e7f4962f676ad631492b2ba4c061 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 31 Aug 2010 17:00:18 -0700 Subject: pid: make setpgid() system call use RCU read-side critical section commit 950eaaca681c44aab87a46225c9e44f902c080aa upstream. [ 23.584719] [ 23.584720] =================================================== [ 23.585059] [ INFO: suspicious rcu_dereference_check() usage. ] [ 23.585176] --------------------------------------------------- [ 23.585176] kernel/pid.c:419 invoked rcu_dereference_check() without protection! [ 23.585176] [ 23.585176] other info that might help us debug this: [ 23.585176] [ 23.585176] [ 23.585176] rcu_scheduler_active = 1, debug_locks = 1 [ 23.585176] 1 lock held by rc.sysinit/728: [ 23.585176] #0: (tasklist_lock){.+.+..}, at: [] sys_setpgid+0x5f/0x193 [ 23.585176] [ 23.585176] stack backtrace: [ 23.585176] Pid: 728, comm: rc.sysinit Not tainted 2.6.36-rc2 #2 [ 23.585176] Call Trace: [ 23.585176] [] lockdep_rcu_dereference+0x99/0xa2 [ 23.585176] [] find_task_by_pid_ns+0x50/0x6a [ 23.585176] [] find_task_by_vpid+0x1d/0x1f [ 23.585176] [] sys_setpgid+0x67/0x193 [ 23.585176] [] system_call_fastpath+0x16/0x1b [ 24.959669] type=1400 audit(1282938522.956:4): avc: denied { module_request } for pid=766 comm="hwclock" kmod="char-major-10-135" scontext=system_u:system_r:hwclock_t:s0 tcontext=system_u:system_r:kernel_t:s0 tclas It turns out that the setpgid() system call fails to enter an RCU read-side critical section before doing a PID-to-task_struct translation. This commit therefore does rcu_read_lock() before the translation, and also does rcu_read_unlock() after the last use of the returned pointer. Reported-by: Andrew Morton Signed-off-by: Paul E. McKenney Acked-by: David Howells Cc: Jiri Slaby Cc: Oleg Nesterov Signed-off-by: Greg Kroah-Hartman --- kernel/sys.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/sys.c b/kernel/sys.c index e83ddbbaf89d..f4fcc6e870ff 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -931,6 +931,7 @@ SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid) pgid = pid; if (pgid < 0) return -EINVAL; + rcu_read_lock(); /* From this point forward we keep holding onto the tasklist lock * so that our parent does not change from under us. -DaveM @@ -984,6 +985,7 @@ SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid) out: /* All paths lead to here, thus we are safe. -DaveM */ write_unlock_irq(&tasklist_lock); + rcu_read_unlock(); return err; } -- cgit v1.2.3 From 22bad8bbb944a2973d3fa3581198fd67c2f40eba Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 14 Sep 2010 16:35:14 +0200 Subject: sched: Fix user time incorrectly accounted as system time on 32-bit commit e75e863dd5c7d96b91ebbd241da5328fc38a78cc upstream. We have 32-bit variable overflow possibility when multiply in task_times() and thread_group_times() functions. When the overflow happens then the scaled utime value becomes erroneously small and the scaled stime becomes i erroneously big. Reported here: https://bugzilla.redhat.com/show_bug.cgi?id=633037 https://bugzilla.kernel.org/show_bug.cgi?id=16559 Reported-by: Michael Chapman Reported-by: Ciriaco Garcia de Celis Signed-off-by: Stanislaw Gruszka Signed-off-by: Peter Zijlstra Cc: Hidetoshi Seto LKML-Reference: <20100914143513.GB8415@redhat.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 6d0dbebc2d7f..4fa520b111d6 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3349,9 +3349,9 @@ void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st) rtime = nsecs_to_cputime(p->se.sum_exec_runtime); if (total) { - u64 temp; + u64 temp = rtime; - temp = (u64)(rtime * utime); + temp *= utime; do_div(temp, total); utime = (cputime_t)temp; } else @@ -3382,9 +3382,9 @@ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) rtime = nsecs_to_cputime(cputime.sum_exec_runtime); if (total) { - u64 temp; + u64 temp = rtime; - temp = (u64)(rtime * cputime.utime); + temp *= cputime.utime; do_div(temp, total); utime = (cputime_t)temp; } else -- cgit v1.2.3 From 6d4179dfe5289f3e7d9c0e4ecb7bf2600404595f Mon Sep 17 00:00:00 2001 From: Patrick Simmons Date: Wed, 8 Sep 2010 10:34:28 -0400 Subject: oprofile: Add Support for Intel CPU Family 6 / Model 22 (Intel Celeron 540) commit c33f543d320843e1732534c3931da4bbd18e6c14 upstream. This patch adds CPU type detection for the Intel Celeron 540, which is part of the Core 2 family according to Wikipedia; the family and ID pair is absent from the Volume 3B table referenced in the source code comments. I have tested this patch on an Intel Celeron 540 machine reporting itself as Family 6 Model 22, and OProfile runs on the machine without issue. Spec: http://download.intel.com/design/mobile/SPECUPDT/317667.pdf Signed-off-by: Patrick Simmons Acked-by: Andi Kleen Acked-by: Arnd Bergmann Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman --- arch/x86/oprofile/nmi_int.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index cfe4faabb0f6..009b819f48d0 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -671,7 +671,9 @@ static int __init ppro_init(char **cpu_type) case 14: *cpu_type = "i386/core"; break; - case 15: case 23: + case 0x0f: + case 0x16: + case 0x17: *cpu_type = "i386/core_2"; break; case 0x1a: -- cgit v1.2.3 From e1d7519864aede29b957d1dc5760d83d9ec2ff3a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 17 Sep 2010 08:22:30 +0100 Subject: drm/i915,agp/intel: Add second set of PCI-IDs for B43 commit 41a51428916ab04587bacee2dda61c4a0c4fc02f upstream. There is a second revision of B43 (a desktop gen4 part) floating around, functionally equivalent to the original B43, so simply add the new PCI-IDs. Bugzilla: https://bugs.freedesktop.org/show_bugs.cgi?id=30221 Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/char/agp/intel-agp.c | 2 ++ drivers/char/agp/intel-agp.h | 2 ++ drivers/gpu/drm/i915/i915_drv.c | 1 + 3 files changed, 5 insertions(+) diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index fe9c6e0b6179..adc0f8931702 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -805,6 +805,8 @@ static const struct intel_driver_description { "G45/G43", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_B43_HB, PCI_DEVICE_ID_INTEL_B43_IG, "B43", NULL, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_B43_1_HB, PCI_DEVICE_ID_INTEL_B43_1_IG, + "B43", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, "G41", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index ffa87b7ff50f..bc9a4ad3bbd3 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -178,6 +178,8 @@ #define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2 #define PCI_DEVICE_ID_INTEL_B43_HB 0x2E40 #define PCI_DEVICE_ID_INTEL_B43_IG 0x2E42 +#define PCI_DEVICE_ID_INTEL_B43_1_HB 0x2E90 +#define PCI_DEVICE_ID_INTEL_B43_1_IG 0x2E92 #define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40 #define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42 #define PCI_DEVICE_ID_INTEL_EAGLELAKE_HB 0x2E00 diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 07a0cf1e3ab5..194e0c4a954b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -175,6 +175,7 @@ static const struct pci_device_id pciidlist[] = { INTEL_VGA_DEVICE(0x2e22, &intel_g45_info), INTEL_VGA_DEVICE(0x2e32, &intel_g45_info), INTEL_VGA_DEVICE(0x2e42, &intel_g45_info), + INTEL_VGA_DEVICE(0x2e92, &intel_g45_info), /* B43_G.1 */ INTEL_VGA_DEVICE(0xa001, &intel_pineview_info), INTEL_VGA_DEVICE(0xa011, &intel_pineview_info), INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info), -- cgit v1.2.3 From 2263d443c405052b413b65506feb3534d375d55c Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 21 Sep 2010 11:48:55 +0200 Subject: bdi: Initialize noop_backing_dev_info properly commit 976e48f8a5b02fc33f3e5cad87fb3fcea041a49c upstream. Properly initialize this backing dev info so that writeback code does not barf when getting to it e.g. via sb->s_bdi. Signed-off-by: Jan Kara Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- mm/backing-dev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 123bcef13e51..c0f715719829 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -29,6 +29,7 @@ EXPORT_SYMBOL_GPL(default_backing_dev_info); struct backing_dev_info noop_backing_dev_info = { .name = "noop", + .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, }; EXPORT_SYMBOL_GPL(noop_backing_dev_info); @@ -254,6 +255,7 @@ static int __init default_bdi_init(void) err = bdi_init(&default_backing_dev_info); if (!err) bdi_register(&default_backing_dev_info, NULL, "default"); + err = bdi_init(&noop_backing_dev_info); return err; } -- cgit v1.2.3 From 0f8f659720f03fcd2fd68384b9fd2ac43535b4be Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 21 Sep 2010 11:49:01 +0200 Subject: char: Mark /dev/zero and /dev/kmem as not capable of writeback commit 371d217ee1ff8b418b8f73fb2a34990f951ec2d4 upstream. These devices don't do any writeback but their device inodes still can get dirty so mark bdi appropriately so that bdi code does the right thing and files inodes to lists of bdi carrying the device inodes. Signed-off-by: Jan Kara Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/char/mem.c | 3 ++- fs/char_dev.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/char/mem.c b/drivers/char/mem.c index a398ecdbd758..1f528fad3516 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -788,10 +788,11 @@ static const struct file_operations zero_fops = { /* * capabilities for /dev/zero * - permits private mappings, "copies" are taken of the source of zeros + * - no writeback happens */ static struct backing_dev_info zero_bdi = { .name = "char/mem", - .capabilities = BDI_CAP_MAP_COPY, + .capabilities = BDI_CAP_MAP_COPY | BDI_CAP_NO_ACCT_AND_WRITEBACK, }; static const struct file_operations full_fops = { diff --git a/fs/char_dev.c b/fs/char_dev.c index f80a4f25123c..143d393881cb 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -40,7 +40,9 @@ struct backing_dev_info directly_mappable_cdev_bdi = { #endif /* permit direct mmap, for read, write or exec */ BDI_CAP_MAP_DIRECT | - BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP), + BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP | + /* no writeback happens */ + BDI_CAP_NO_ACCT_AND_WRITEBACK), }; static struct kobj_map *cdev_map; -- cgit v1.2.3 From b932db652630421d4a75e3b661995962a856bf64 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 22 Sep 2010 13:05:11 -0700 Subject: drivers/pci/intel-iommu.c: fix build with older gcc's commit df08cdc7ef606509debe7677c439be0ca48790e4 upstream. drivers/pci/intel-iommu.c: In function `__iommu_calculate_agaw': drivers/pci/intel-iommu.c:437: sorry, unimplemented: inlining failed in call to 'width_to_agaw': function body not available drivers/pci/intel-iommu.c:445: sorry, unimplemented: called from here Move the offending function (and its siblings) to top-of-file, remove the forward declaration. Addresses https://bugzilla.kernel.org/show_bug.cgi?id=17441 Reported-by: Martin Mokrejs Cc: David Woodhouse Cc: Jesse Barnes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/pci/intel-iommu.c | 90 ++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 47 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 435fbbc2b273..8e499e8d2481 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -71,6 +71,49 @@ #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) #define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64)) +/* page table handling */ +#define LEVEL_STRIDE (9) +#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1) + +static inline int agaw_to_level(int agaw) +{ + return agaw + 2; +} + +static inline int agaw_to_width(int agaw) +{ + return 30 + agaw * LEVEL_STRIDE; +} + +static inline int width_to_agaw(int width) +{ + return (width - 30) / LEVEL_STRIDE; +} + +static inline unsigned int level_to_offset_bits(int level) +{ + return (level - 1) * LEVEL_STRIDE; +} + +static inline int pfn_level_offset(unsigned long pfn, int level) +{ + return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK; +} + +static inline unsigned long level_mask(int level) +{ + return -1UL << level_to_offset_bits(level); +} + +static inline unsigned long level_size(int level) +{ + return 1UL << level_to_offset_bits(level); +} + +static inline unsigned long align_to_level(unsigned long pfn, int level) +{ + return (pfn + level_size(level) - 1) & level_mask(level); +} /* VT-d pages must always be _smaller_ than MM pages. Otherwise things are never going to work. */ @@ -434,8 +477,6 @@ void free_iova_mem(struct iova *iova) } -static inline int width_to_agaw(int width); - static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw) { unsigned long sagaw; @@ -646,51 +687,6 @@ out: spin_unlock_irqrestore(&iommu->lock, flags); } -/* page table handling */ -#define LEVEL_STRIDE (9) -#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1) - -static inline int agaw_to_level(int agaw) -{ - return agaw + 2; -} - -static inline int agaw_to_width(int agaw) -{ - return 30 + agaw * LEVEL_STRIDE; - -} - -static inline int width_to_agaw(int width) -{ - return (width - 30) / LEVEL_STRIDE; -} - -static inline unsigned int level_to_offset_bits(int level) -{ - return (level - 1) * LEVEL_STRIDE; -} - -static inline int pfn_level_offset(unsigned long pfn, int level) -{ - return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK; -} - -static inline unsigned long level_mask(int level) -{ - return -1UL << level_to_offset_bits(level); -} - -static inline unsigned long level_size(int level) -{ - return 1UL << level_to_offset_bits(level); -} - -static inline unsigned long align_to_level(unsigned long pfn, int level) -{ - return (pfn + level_size(level) - 1) & level_mask(level); -} - static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, unsigned long pfn) { -- cgit v1.2.3 From e675865c92e66331dba733c544eb53b3d6c45eaa Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Wed, 22 Sep 2010 13:05:12 -0700 Subject: mmap: call unlink_anon_vmas() in __split_vma() in case of error commit 2aeadc30de45a72648f271603203ab392b80f607 upstream. If __split_vma fails because of an out of memory condition the anon_vma_chain isn't teardown and freed potentially leading to rmap walks accessing freed vma information plus there's a memleak. Signed-off-by: Andrea Arcangeli Acked-by: Johannes Weiner Acked-by: Rik van Riel Acked-by: Hugh Dickins Cc: Marcelo Tosatti Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mmap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/mmap.c b/mm/mmap.c index 3867cfc21cc7..12d38bf4f5b0 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1997,6 +1997,7 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, removed_exe_file_vma(mm); fput(new->vm_file); } + unlink_anon_vmas(new); out_free_mpol: mpol_put(pol); out_free_vma: -- cgit v1.2.3 From a3bec3ef92a0395e64b5ac67640f420bfabe1bab Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 22 Sep 2010 13:05:09 -0700 Subject: drivers/video/sis/sis_main.c: prevent reading uninitialized stack memory commit fd02db9de73faebc51240619c7c7f99bee9f65c7 upstream. The FBIOGET_VBLANK device ioctl allows unprivileged users to read 16 bytes of uninitialized stack memory, because the "reserved" member of the fb_vblank struct declared on the stack is not altered or zeroed before being copied back to the user. This patch takes care of it. Signed-off-by: Dan Rosenberg Cc: Thomas Winischhofer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/video/sis/sis_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 559bf1727a2b..b52f8e4ef1fd 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -1701,6 +1701,9 @@ static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, break; case FBIOGET_VBLANK: + + memset(&sisvbblank, 0, sizeof(struct fb_vblank)); + sisvbblank.count = 0; sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount); -- cgit v1.2.3 From e658aee24443e17c08424ae4ce193735c7fde737 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 22 Sep 2010 13:05:13 -0700 Subject: rtc: s3c: balance state changes of wakeup flag commit f501ed524b26ba1b739b7f7feb0a0e1496878769 upstream. This change resolves a problem about unbalanced calls of enable_irq_wakeup() and disable_irq_wakeup() for alarm interrupt. Bug reproduction: root@eb600:~# echo 0 > /sys/class/rtc/rtc0/wakealarm WARNING: at kernel/irq/manage.c:361 set_irq_wake+0x7c/0xe4() Unbalanced IRQ 46 wake disable Modules linked in: [] (unwind_backtrace+0x0/0xd8) from [] (warn_slowpath_common+0x44/0x5c) [] (warn_slowpath_common+0x44/0x5c) from [] (warn_slowpath_fmt+0x24/0x30) [] (warn_slowpath_fmt+0x24/0x30) from [] (set_irq_wake+0x7c/0xe4) [] (set_irq_wake+0x7c/0xe4) from [] (s3c_rtc_setalarm+0xa8/0xb8) [] (s3c_rtc_setalarm+0xa8/0xb8) from [] (rtc_set_alarm+0x60/0x74) [] (rtc_set_alarm+0x60/0x74) from [] (rtc_sysfs_set_wakealarm+0xc8/0xd8) [] (rtc_sysfs_set_wakealarm+0xc8/0xd8) from [] (dev_attr_store+0x20/0x24) [] (dev_attr_store+0x20/0x24) from [] (sysfs_write_file+0x104/0x13c) [] (sysfs_write_file+0x104/0x13c) from [] (vfs_write+0xb0/0x158) [] (vfs_write+0xb0/0x158) from [] (sys_write+0x3c/0x68) [] (sys_write+0x3c/0x68) from [] (ret_fast_syscall+0x0/0x28) Signed-off-by: Vladimir Zapolskiy Cc: Alessandro Zummo Cc: Ben Dooks Cc: Atul Dahiya Cc: Taekgyun Ko Cc: Kukjin Kim Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-s3c.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 70b68d35f969..2a305ef579a7 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -298,11 +298,6 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) s3c_rtc_setaie(alrm->enabled); - if (alrm->enabled) - enable_irq_wake(s3c_rtc_alarmno); - else - disable_irq_wake(s3c_rtc_alarmno); - return 0; } @@ -547,6 +542,10 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) ticnt_en_save &= S3C64XX_RTCCON_TICEN; } s3c_rtc_enable(pdev, 0); + + if (device_may_wakeup(&pdev->dev)) + enable_irq_wake(s3c_rtc_alarmno); + return 0; } @@ -560,6 +559,10 @@ static int s3c_rtc_resume(struct platform_device *pdev) tmp = readb(s3c_rtc_base + S3C2410_RTCCON); writeb(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); } + + if (device_may_wakeup(&pdev->dev)) + disable_irq_wake(s3c_rtc_alarmno); + return 0; } #else -- cgit v1.2.3 From 32e987bf2db7941e5a27bfa4dbed50663c5b1ba2 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 22 Sep 2010 14:32:56 -0400 Subject: Prevent freeing uninitialized pointer in compat_do_readv_writev commit 767b68e96993e29e3480d7ecdd9c4b84667c5762 upstream. In 32-bit compatibility mode, the error handling for compat_do_readv_writev() may free an uninitialized pointer, potentially leading to all sorts of ugly memory corruption. This is reliably triggerable by unprivileged users by invoking the readv()/writev() syscalls with an invalid iovec pointer. The below patch fixes this to emulate the non-compat version. Introduced by commit b83733639a49 ("compat: factor out compat_rw_copy_check_uvector from compat_do_readv_writev") Signed-off-by: Dan Rosenberg Cc: Al Viro Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/compat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/compat.c b/fs/compat.c index 6490d2134ff3..af7c2301a2ec 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1150,7 +1150,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file, { compat_ssize_t tot_len; struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov; + struct iovec *iov = iovstack; ssize_t ret; io_fn_t fn; iov_fn_t fnv; -- cgit v1.2.3 From db42f7e4f8cdd2e25ab838365f4bfb6b328289da Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 22 Sep 2010 13:04:54 -0700 Subject: /proc/vmcore: fix seeking commit c227e69028473c7c7994a9b0a2cc0034f3f7e0fe upstream. Commit 73296bc611 ("procfs: Use generic_file_llseek in /proc/vmcore") broke seeking on /proc/vmcore. This changes it back to use default_llseek in order to restore the original behaviour. The problem with generic_file_llseek is that it only allows seeks up to inode->i_sb->s_maxbytes, which is zero on procfs and some other virtual file systems. We should merge generic_file_llseek and default_llseek some day and clean this up in a proper way, but for 2.6.35/36, reverting vmcore is the safer solution. Signed-off-by: Arnd Bergmann Cc: Frederic Weisbecker Reported-by: CAI Qian Tested-by: CAI Qian Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/proc/vmcore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 91c817ff02c3..2367fb3f70bc 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c @@ -163,7 +163,7 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer, static const struct file_operations proc_vmcore_operations = { .read = read_vmcore, - .llseek = generic_file_llseek, + .llseek = default_llseek, }; static struct vmcore* __init get_new_element(void) -- cgit v1.2.3 From ee71a393b8612fc2b89fdac0f2a3056972cdd3f9 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Wed, 22 Sep 2010 13:05:01 -0700 Subject: vmscan: check all_unreclaimable in direct reclaim path commit d1908362ae0b97374eb8328fbb471576332f9fb1 upstream. M. Vefa Bicakci reported 2.6.35 kernel hang up when hibernation on his 32bit 3GB mem machine. (https://bugzilla.kernel.org/show_bug.cgi?id=16771). Also he bisected the regression to commit bb21c7ce18eff8e6e7877ca1d06c6db719376e3c Author: KOSAKI Motohiro Date: Fri Jun 4 14:15:05 2010 -0700 vmscan: fix do_try_to_free_pages() return value when priority==0 reclaim failure At first impression, this seemed very strange because the above commit only chenged function return value and hibernate_preallocate_memory() ignore return value of shrink_all_memory(). But it's related. Now, page allocation from hibernation code may enter infinite loop if the system has highmem. The reasons are that vmscan don't care enough OOM case when oom_killer_disabled. The problem sequence is following as. 1. hibernation 2. oom_disable 3. alloc_pages 4. do_try_to_free_pages if (scanning_global_lru(sc) && !all_unreclaimable) return 1; If kswapd is not freozen, it would set zone->all_unreclaimable to 1 and then shrink_zones maybe return true(ie, all_unreclaimable is true). So at last, alloc_pages could go to _nopage_. If it is, it should have no problem. This patch adds all_unreclaimable check to protect in direct reclaim path, too. It can care of hibernation OOM case and help bailout all_unreclaimable case slightly. Signed-off-by: KOSAKI Motohiro Signed-off-by: Minchan Kim Reported-by: M. Vefa Bicakci Reported-by: Reviewed-by: Johannes Weiner Tested-by: Acked-by: Rafael J. Wysocki Acked-by: Rik van Riel Acked-by: KAMEZAWA Hiroyuki Cc: Balbir Singh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/vmscan.c | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index b94fe1b3da43..975362619e19 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1726,13 +1726,12 @@ static void shrink_zone(int priority, struct zone *zone, * If a zone is deemed to be full of pinned pages then just give it a light * scan then give up on it. */ -static bool shrink_zones(int priority, struct zonelist *zonelist, +static void shrink_zones(int priority, struct zonelist *zonelist, struct scan_control *sc) { enum zone_type high_zoneidx = gfp_zone(sc->gfp_mask); struct zoneref *z; struct zone *zone; - bool all_unreclaimable = true; for_each_zone_zonelist_nodemask(zone, z, zonelist, high_zoneidx, sc->nodemask) { @@ -1759,8 +1758,38 @@ static bool shrink_zones(int priority, struct zonelist *zonelist, } shrink_zone(priority, zone, sc); - all_unreclaimable = false; } +} + +static bool zone_reclaimable(struct zone *zone) +{ + return zone->pages_scanned < zone_reclaimable_pages(zone) * 6; +} + +/* + * As hibernation is going on, kswapd is freezed so that it can't mark + * the zone into all_unreclaimable. It can't handle OOM during hibernation. + * So let's check zone's unreclaimable in direct reclaim as well as kswapd. + */ +static bool all_unreclaimable(struct zonelist *zonelist, + struct scan_control *sc) +{ + struct zoneref *z; + struct zone *zone; + bool all_unreclaimable = true; + + for_each_zone_zonelist_nodemask(zone, z, zonelist, + gfp_zone(sc->gfp_mask), sc->nodemask) { + if (!populated_zone(zone)) + continue; + if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL)) + continue; + if (zone_reclaimable(zone)) { + all_unreclaimable = false; + break; + } + } + return all_unreclaimable; } @@ -1784,7 +1813,6 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, struct scan_control *sc) { int priority; - bool all_unreclaimable; unsigned long total_scanned = 0; struct reclaim_state *reclaim_state = current->reclaim_state; unsigned long lru_pages = 0; @@ -1815,7 +1843,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, sc->nr_scanned = 0; if (!priority) disable_swap_token(); - all_unreclaimable = shrink_zones(priority, zonelist, sc); + shrink_zones(priority, zonelist, sc); /* * Don't shrink slabs when reclaiming memory from * over limit cgroups @@ -1879,7 +1907,7 @@ out: return sc->nr_reclaimed; /* top priority shrink_zones still had more to do? don't OOM, then */ - if (scanning_global_lru(sc) && !all_unreclaimable) + if (scanning_global_lru(sc) && !all_unreclaimable(zonelist, sc)) return 1; return 0; @@ -2137,8 +2165,7 @@ loop_again: total_scanned += sc.nr_scanned; if (zone->all_unreclaimable) continue; - if (nr_slab == 0 && - zone->pages_scanned >= (zone_reclaimable_pages(zone) * 6)) + if (nr_slab == 0 && !zone_reclaimable(zone)) zone->all_unreclaimable = 1; /* * If we've done a decent amount of scanning and -- cgit v1.2.3 From 3cc932ba7fa6f24a84c18a581eae1269dc31efef Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 21 Sep 2010 07:57:19 +0200 Subject: percpu: fix pcpu_last_unit_cpu commit 46b30ea9bc3698bc1d1e6fd726c9601d46fa0a91 upstream. pcpu_first/last_unit_cpu are used to track which cpu has the first and last units assigned. This in turn is used to determine the span of a chunk for man/unmap cache flushes and whether an address belongs to the first chunk or not in per_cpu_ptr_to_phys(). When the number of possible CPUs isn't power of two, a chunk may contain unassigned units towards the end of a chunk. The logic to determine pcpu_last_unit_cpu was incorrect when there was an unused unit at the end of a chunk. It failed to ignore the unused unit and assigned the unused marker NR_CPUS to pcpu_last_unit_cpu. This was discovered through kdump failure which was caused by malfunctioning per_cpu_ptr_to_phys() on a kvm setup with 50 possible CPUs by CAI Qian. Signed-off-by: Tejun Heo Reported-by: CAI Qian Signed-off-by: Greg Kroah-Hartman --- mm/percpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/percpu.c b/mm/percpu.c index 6470e7710231..0a09fff3d05d 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -1413,9 +1413,9 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, if (pcpu_first_unit_cpu == NR_CPUS) pcpu_first_unit_cpu = cpu; + pcpu_last_unit_cpu = cpu; } } - pcpu_last_unit_cpu = cpu; pcpu_nr_units = unit; for_each_possible_cpu(cpu) -- cgit v1.2.3 From 94c195797a9c05cb34426abb0fd38d254d293591 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 22 Sep 2010 13:05:03 -0700 Subject: aio: do not return ERESTARTSYS as a result of AIO commit a0c42bac79731276c9b2f28d54f9e658fcf843a2 upstream. OCFS2 can return ERESTARTSYS from its write function when the process is signalled while waiting for a cluster lock (and the filesystem is mounted with intr mount option). Generally, it seems reasonable to allow filesystems to return this error code from its IO functions. As we must not leak ERESTARTSYS (and similar error codes) to userspace as a result of an AIO operation, we have to properly convert it to EINTR inside AIO code (restarting the syscall isn't really an option because other AIO could have been already submitted by the same io_submit syscall). Signed-off-by: Jan Kara Reviewed-by: Jeff Moyer Cc: Christoph Hellwig Cc: Zach Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/aio.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/aio.c b/fs/aio.c index 1ccf25cef1f0..25c815dc4b96 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -712,8 +712,16 @@ static ssize_t aio_run_iocb(struct kiocb *iocb) */ ret = retry(iocb); - if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) + if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) { + /* + * There's no easy way to restart the syscall since other AIO's + * may be already running. Just fail this IO with EINTR. + */ + if (unlikely(ret == -ERESTARTSYS || ret == -ERESTARTNOINTR || + ret == -ERESTARTNOHAND || ret == -ERESTART_RESTARTBLOCK)) + ret = -EINTR; aio_complete(iocb, ret, 0); + } out: spin_lock_irq(&ctx->ctx_lock); -- cgit v1.2.3 From 1d506ee42d387f84cd063fff8014d8decc1875c4 Mon Sep 17 00:00:00 2001 From: Jeff Moyer Date: Fri, 10 Sep 2010 14:16:00 -0700 Subject: aio: check for multiplication overflow in do_io_submit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 75e1c70fc31490ef8a373ea2a4bea2524099b478 upstream. Tavis Ormandy pointed out that do_io_submit does not do proper bounds checking on the passed-in iocb array:        if (unlikely(nr < 0))                return -EINVAL;        if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(iocbpp)))))                return -EFAULT;                      ^^^^^^^^^^^^^^^^^^ The attached patch checks for overflow, and if it is detected, the number of iocbs submitted is scaled down to a number that will fit in the long.  This is an ok thing to do, as sys_io_submit is documented as returning the number of iocbs submitted, so callers should handle a return value of less than the 'nr' argument passed in. Reported-by: Tavis Ormandy Signed-off-by: Jeff Moyer Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/aio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/aio.c b/fs/aio.c index 25c815dc4b96..5fb0fd7c80a0 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1667,6 +1667,9 @@ long do_io_submit(aio_context_t ctx_id, long nr, if (unlikely(nr < 0)) return -EINVAL; + if (unlikely(nr > LONG_MAX/sizeof(*iocbpp))) + nr = LONG_MAX/sizeof(*iocbpp); + if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp))))) return -EFAULT; -- cgit v1.2.3 From 06a351856476ca85b2aba3161522ade9b2ab6cdb Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 21 May 2010 16:18:09 +0200 Subject: x86 platform drivers: hp-wmi Reorder event id processing commit 751ae808f6b29803228609f51aa1ae057f5c576e upstream. Event id 0x4 defines the hotkey event. No need (or even wrong) to query HPWMI_HOTKEY_QUERY if event id is != 0x4. Reorder the eventcode conditionals and use switch case instead of if/else. Use an enum for the event ids cases. Signed-off-by: Thomas Renninger Signed-off-by: Matthew Garrett CC: linux-acpi@vger.kernel.org CC: platform-driver-x86@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/hp-wmi.c | 51 +++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 51c07a05a7bc..f1c186245f98 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -58,6 +58,12 @@ enum hp_wmi_radio { HPWMI_WWAN = 2, }; +enum hp_wmi_event_ids { + HPWMI_DOCK_EVENT = 1, + HPWMI_BEZEL_BUTTON = 4, + HPWMI_WIRELESS = 5, +}; + static int __devinit hp_wmi_bios_setup(struct platform_device *device); static int __exit hp_wmi_bios_remove(struct platform_device *device); static int hp_wmi_resume_handler(struct device *device); @@ -338,7 +344,7 @@ static void hp_wmi_notify(u32 value, void *context) struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; static struct key_entry *key; union acpi_object *obj; - int eventcode; + int eventcode, key_code; acpi_status status; status = wmi_get_event_data(value, &response); @@ -357,28 +363,32 @@ static void hp_wmi_notify(u32 value, void *context) eventcode = *((u8 *) obj->buffer.pointer); kfree(obj); - if (eventcode == 0x4) - eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, - 0); - key = hp_wmi_get_entry_by_scancode(eventcode); - if (key) { - switch (key->type) { - case KE_KEY: - input_report_key(hp_wmi_input_dev, - key->keycode, 1); - input_sync(hp_wmi_input_dev); - input_report_key(hp_wmi_input_dev, - key->keycode, 0); - input_sync(hp_wmi_input_dev); - break; - } - } else if (eventcode == 0x1) { + switch (eventcode) { + case HPWMI_DOCK_EVENT: input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state()); input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, hp_wmi_tablet_state()); input_sync(hp_wmi_input_dev); - } else if (eventcode == 0x5) { + break; + case HPWMI_BEZEL_BUTTON: + key_code = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, + 0); + key = hp_wmi_get_entry_by_scancode(key_code); + if (key) { + switch (key->type) { + case KE_KEY: + input_report_key(hp_wmi_input_dev, + key->keycode, 1); + input_sync(hp_wmi_input_dev); + input_report_key(hp_wmi_input_dev, + key->keycode, 0); + input_sync(hp_wmi_input_dev); + break; + } + } + break; + case HPWMI_WIRELESS: if (wifi_rfkill) rfkill_set_states(wifi_rfkill, hp_wmi_get_sw_state(HPWMI_WIFI), @@ -391,9 +401,12 @@ static void hp_wmi_notify(u32 value, void *context) rfkill_set_states(wwan_rfkill, hp_wmi_get_sw_state(HPWMI_WWAN), hp_wmi_get_hw_state(HPWMI_WWAN)); - } else + break; + default: printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n", eventcode); + break; + } } static int __init hp_wmi_input_setup(void) -- cgit v1.2.3 From 2e4e3bb743cc3dfe09fd39aa6bd3aea6a19e5286 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 9 Sep 2010 14:45:00 +0100 Subject: GFS2: gfs2_logd should be using interruptible waits commit 5f4874903df3562b9d5649fc1cf7b8c6bb238e42 upstream. Looks like this crept in, in a recent update. Reported-by: Krzysztof Urbaniak Signed-off-by: Steven Whitehouse Signed-off-by: Greg Kroah-Hartman --- fs/gfs2/log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 6a857e24f947..83917b50a196 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -932,7 +932,7 @@ int gfs2_logd(void *data) do { prepare_to_wait(&sdp->sd_logd_waitq, &wait, - TASK_UNINTERRUPTIBLE); + TASK_INTERRUPTIBLE); if (!gfs2_ail_flush_reqd(sdp) && !gfs2_jrnl_flush_reqd(sdp) && !kthread_should_stop()) -- cgit v1.2.3 From b85ec83e1e6dc064f6623378a8f3b402a001ade7 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Sun, 22 Aug 2010 20:54:08 +0200 Subject: drm/nv50: initialize ramht_refs list for faked 0 channel commit 615661f3948a066fd22a36fe8ea0c528b75ee373 upstream. We need it for PFIFO_INTR_CACHE_ERROR interrupt handling, because nouveau_fifo_swmthd looks for matching gpuobj in ramht_refs list. It fixes kernel panic in nouveau_gpuobj_ref_find. Signed-off-by: Marcin Slusarz Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nv50_instmem.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c index 5f21df31f3aa..3fcae5488d6d 100644 --- a/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c @@ -141,6 +141,8 @@ nv50_instmem_init(struct drm_device *dev) chan->file_priv = (struct drm_file *)-2; dev_priv->fifos[0] = dev_priv->fifos[127] = chan; + INIT_LIST_HEAD(&chan->ramht_refs); + /* Channel's PRAMIN object + heap */ ret = nouveau_gpuobj_new_fake(dev, 0, c_offset, c_size, 0, NULL, &chan->ramin); -- cgit v1.2.3 From f4254199838237a0b7df93474cf6b4f46c0b0a4a Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 28 Jul 2010 10:18:37 -0400 Subject: inotify: send IN_UNMOUNT events commit 611da04f7a31b2208e838be55a42c7a1310ae321 upstream. Since the .31 or so notify rewrite inotify has not sent events about inodes which are unmounted. This patch restores those events. Signed-off-by: Eric Paris Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- fs/notify/inotify/inotify_user.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index e46ca685b9be..0c6bbc031f15 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -96,8 +96,11 @@ static inline __u32 inotify_arg_to_mask(u32 arg) { __u32 mask; - /* everything should accept their own ignored and cares about children */ - mask = (FS_IN_IGNORED | FS_EVENT_ON_CHILD); + /* + * everything should accept their own ignored, cares about children, + * and should receive events when the inode is unmounted + */ + mask = (FS_IN_IGNORED | FS_EVENT_ON_CHILD | FS_UNMOUNT); /* mask off the flags used to open the fd */ mask |= (arg & (IN_ALL_EVENTS | IN_ONESHOT)); -- cgit v1.2.3 From 80e1809cb470846bd477c8ee041262d1483c0dc8 Mon Sep 17 00:00:00 2001 From: Ryan Kuester Date: Mon, 26 Apr 2010 18:11:54 -0500 Subject: SCSI: mptsas: fix hangs caused by ATA pass-through commit 2a1b7e575b80ceb19ea50bfa86ce0053ea57181d upstream. I may have an explanation for the LSI 1068 HBA hangs provoked by ATA pass-through commands, in particular by smartctl. First, my version of the symptoms. On an LSI SAS1068E B3 HBA running 01.29.00.00 firmware, with SATA disks, and with smartd running, I'm seeing occasional task, bus, and host resets, some of which lead to hard faults of the HBA requiring a reboot. Abusively looping the smartctl command, # while true; do smartctl -a /dev/sdb > /dev/null; done dramatically increases the frequency of these failures to nearly one per minute. A high IO load through the HBA while looping smartctl seems to improve the chance of a full scsi host reset or a non-recoverable hang. I reduced what smartctl was doing down to a simple test case which causes the hang with a single IO when pointed at the sd interface. See the code at the bottom of this e-mail. It uses an SG_IO ioctl to issue a single pass-through ATA identify device command. If the buffer userspace gives for the read data has certain alignments, the task is issued to the HBA but the HBA fails to respond. If run against the sg interface, neither the test code nor smartctl causes a hang. sd and sg handle the SG_IO ioctl slightly differently. Unless you specifically set a flag to do direct IO, sg passes a buffer of its own, which is page-aligned, to the block layer and later copies the result into the userspace buffer regardless of its alignment. sd, on the other hand, always does direct IO unless the userspace buffer fails an alignment test at block/blk-map.c line 57, in which case a page-aligned buffer is created and used for the transfer. The alignment test currently checks for word-alignment, the default setup by scsi_lib.c; therefore, userspace buffers of almost any alignment are given directly to the HBA as DMA targets. The LSI 1068 hardware doesn't seem to like at least a couple of the alignments which cross a page boundary (see the test code below). Curiously, many page-boundary-crossing alignments do work just fine. So, either the hardware has an bug handling certain alignments or the hardware has a stricter alignment requirement than the driver is advertising. If stricter alignment is required, then in no case should misaligned buffers from userspace be allowed through without being bounced or at least causing an error to be returned. It seems the mptsas driver could use blk_queue_dma_alignment() to advertise a stricter alignment requirement. If it does, sd does the right thing and bounces misaligned buffers (see block/blk-map.c line 57). The following patch to 2.6.34-rc5 makes my symptoms go away. I'm sure this is the wrong place for this code, but it gets my idea across. Acked-by: Kashyap Desai Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/message/fusion/mptscsih.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 5c53624e0e87..407cb84822df 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -2459,6 +2459,8 @@ mptscsih_slave_configure(struct scsi_device *sdev) ioc->name,sdev->tagged_supported, sdev->simple_tags, sdev->ordered_tags)); + blk_queue_dma_alignment (sdev->request_queue, 512 - 1); + return 0; } -- cgit v1.2.3 From 1be501980f140e5a6698999df9c7c6124c14810f Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Fri, 17 Sep 2010 13:13:13 -0300 Subject: KVM: Keep slot ID in memory slot structure commit e36d96f7cfaa71870c407131eb4fbd38ea285c01 upstream. May be used for distinguishing between internal and user slots, or for sorting slots in size order. Signed-off-by: Avi Kivity Cc: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- include/linux/kvm_host.h | 1 + virt/kvm/kvm_main.c | 1 + 2 files changed, 2 insertions(+) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 7cb116afa1cd..f24d8fc51970 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -123,6 +123,7 @@ struct kvm_memory_slot { } *lpage_info[KVM_NR_PAGE_SIZES - 1]; unsigned long userspace_addr; int user_alloc; + int id; }; static inline unsigned long kvm_dirty_bitmap_bytes(struct kvm_memory_slot *memslot) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index f032806a212f..277452851313 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -566,6 +566,7 @@ int __kvm_set_memory_region(struct kvm *kvm, new = old = *memslot; + new.id = mem->slot; new.base_gfn = base_gfn; new.npages = npages; new.flags = mem->flags; -- cgit v1.2.3 From aaf270ed0cb87db6a037a682a3d2f860efb32f59 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Fri, 17 Sep 2010 13:13:14 -0300 Subject: KVM: Prevent internal slots from being COWed commit 7ac77099ce88a0c31b75acd0ec5ef3da4415a6d8 upstream. If a process with a memory slot is COWed, the page will change its address (despite having an elevated reference count). This breaks internal memory slots which have their physical addresses loaded into vmcs registers (see the APIC access memory slot). Signed-off-by: Avi Kivity Cc: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/x86.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 7fa89c39c64f..fd2268838ca2 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5438,6 +5438,11 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, int user_alloc) { int npages = memslot->npages; + int map_flags = MAP_PRIVATE | MAP_ANONYMOUS; + + /* Prevent internal slot pages from being moved by fork()/COW. */ + if (memslot->id >= KVM_MEMORY_SLOTS) + map_flags = MAP_SHARED | MAP_ANONYMOUS; /*To keep backward compatibility with older userspace, *x86 needs to hanlde !user_alloc case. @@ -5450,7 +5455,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, userspace_addr = do_mmap(NULL, 0, npages * PAGE_SIZE, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, + map_flags, 0); up_write(¤t->mm->mmap_sem); -- cgit v1.2.3 From 724b86b0bcd26cda145915e2991952f23e0775d2 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Fri, 17 Sep 2010 13:13:15 -0300 Subject: KVM: MMU: fix direct sp's access corrupted commit 9e7b0e7fba45ca3c6357aeb7091ebc281f1de365 upstream. If the mapping is writable but the dirty flag is not set, we will find the read-only direct sp and setup the mapping, then if the write #PF occur, we will mark this mapping writable in the read-only direct sp, now, other real read-only mapping will happily write it without #PF. It may hurt guest's COW Fixed by re-install the mapping when write #PF occur. Signed-off-by: Xiao Guangrong Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/paging_tmpl.h | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 2331bdc2b549..e34452b92928 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -324,8 +324,32 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, break; } - if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep)) - continue; + if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep)) { + struct kvm_mmu_page *child; + unsigned direct_access; + + if (level != gw->level) + continue; + + /* + * For the direct sp, if the guest pte's dirty bit + * changed form clean to dirty, it will corrupt the + * sp's access: allow writable in the read-only sp, + * so we should update the spte at this point to get + * a new sp with the correct access. + */ + direct_access = gw->pt_access & gw->pte_access; + if (!is_dirty_gpte(gw->ptes[gw->level - 1])) + direct_access &= ~ACC_WRITE_MASK; + + child = page_header(*sptep & PT64_BASE_ADDR_MASK); + if (child->role.access == direct_access) + continue; + + mmu_page_remove_parent_pte(child, sptep); + __set_spte(sptep, shadow_trap_nonpresent_pte); + kvm_flush_remote_tlbs(vcpu->kvm); + } if (is_large_pte(*sptep)) { rmap_remove(vcpu->kvm, sptep); -- cgit v1.2.3 From 41d2a3bcdb188e4d6d8cc799f93aed93c0639e36 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Fri, 17 Sep 2010 13:13:16 -0300 Subject: KVM: x86: emulator: inc/dec can have lock prefix commit c0e0608cb902af1a1fd8d413ec0a07ee1e62c652 upstream. Mark inc (0xfe/0 0xff/0) and dec (0xfe/1 0xff/1) as lock prefix capable. Signed-off-by: Gleb Natapov Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/emulate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 5ac0bb465ed6..715a7fa42be6 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -345,10 +345,10 @@ static u32 group_table[] = { DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM, 0, 0, 0, 0, [Group4*8] = - ByteOp | DstMem | SrcNone | ModRM, ByteOp | DstMem | SrcNone | ModRM, + ByteOp | DstMem | SrcNone | ModRM | Lock, ByteOp | DstMem | SrcNone | ModRM | Lock, 0, 0, 0, 0, 0, 0, [Group5*8] = - DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM, + DstMem | SrcNone | ModRM | Lock, DstMem | SrcNone | ModRM | Lock, SrcMem | ModRM | Stack, 0, SrcMem | ModRM | Stack, SrcMem | ModRM | Src2Mem16 | ImplicitOps, SrcMem | ModRM | Stack, 0, -- cgit v1.2.3 From 291e06417553bbca9d6cf59d5ac1040a9d71da99 Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Fri, 17 Sep 2010 13:13:17 -0300 Subject: KVM: MMU: fix mmu notifier invalidate handler for huge spte commit 6e3e243c3b6e0bbd18c6ce0fbc12bc3fe2d77b34 upstream. The index wasn't calculated correctly (off by one) for huge spte so KVM guest was unstable with transparent hugepages. Signed-off-by: Andrea Arcangeli Reviewed-by: Reviewed-by: Rik van Riel Signed-off-by: Avi Kivity Cc: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/mmu.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index b1ed0a1a5913..92b6ca4fb54d 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -799,8 +799,12 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva, ret = handler(kvm, &memslot->rmap[gfn_offset], data); for (j = 0; j < KVM_NR_PAGE_SIZES - 1; ++j) { - int idx = gfn_offset; - idx /= KVM_PAGES_PER_HPAGE(PT_DIRECTORY_LEVEL + j); + unsigned long idx; + int nr; + + nr = KVM_PAGES_PER_HPAGE(PT_DIRECTORY_LEVEL+j); + idx = (memslot->base_gfn+gfn_offset) / nr - + memslot->base_gfn / nr; ret |= handler(kvm, &memslot->lpage_info[j][idx].rmap_pde, data); -- cgit v1.2.3 From d963ca2b66d33935a858dc01a899dec0b3c77fc9 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Fri, 17 Sep 2010 13:13:18 -0300 Subject: KVM: VMX: Fix host GDT.LIMIT corruption commit 3444d7da1839b851eefedd372978d8a982316c36 upstream. vmx does not restore GDT.LIMIT to the host value, instead it sets it to 64KB. This means host userspace can learn a few bits of host memory. Fix by reloading GDTR when we load other host state. Signed-off-by: Avi Kivity Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/vmx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index ee03679efe78..7d043883d9bc 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -177,6 +177,7 @@ static u64 construct_eptp(unsigned long root_hpa); static DEFINE_PER_CPU(struct vmcs *, vmxarea); static DEFINE_PER_CPU(struct vmcs *, current_vmcs); static DEFINE_PER_CPU(struct list_head, vcpus_on_cpu); +static DEFINE_PER_CPU(struct desc_ptr, host_gdt); static unsigned long *vmx_io_bitmap_a; static unsigned long *vmx_io_bitmap_b; @@ -812,6 +813,7 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); } #endif + load_gdt(&__get_cpu_var(host_gdt)); } static void vmx_load_host_state(struct vcpu_vmx *vmx) @@ -1314,6 +1316,8 @@ static int hardware_enable(void *garbage) ept_sync_global(); + store_gdt(&__get_cpu_var(host_gdt)); + return 0; } -- cgit v1.2.3 From 749d278c05e0d81327647ba7ea71bf01422844c2 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Thu, 9 Sep 2010 15:16:56 -0700 Subject: IA64: fix siglock commit f574c843191728d9407b766a027f779dcd27b272 upstream. When ia64 converted to using ticket locks, an inline implementation of trylock/unlock in fsys.S was missed. This was not noticed because in most circumstances it simply resulted in using the slow path because the siglock was apparently not available (under old spinlock rules). Problems occur when the ticket spinlock has value 0x0 (when first initialised, or when it wraps around). At this point the fsys.S code acquires the lock (changing the 0x0 to 0x1. If another process attempts to get the lock at this point, it will change the value from 0x1 to 0x2 (using new ticket lock rules). Then the fsys.S code will free the lock using old spinlock rules by writing 0x0 to it. From here a variety of bad things can happen. Signed-off-by: Tony Luck Signed-off-by: Greg Kroah-Hartman --- arch/ia64/kernel/fsys.S | 46 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index 3567d54f8cee..471a1e783aca 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S @@ -424,14 +424,26 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set andcm r14=r14,r17 // filter out SIGKILL & SIGSTOP #ifdef CONFIG_SMP - mov r17=1 - ;; - cmpxchg4.acq r18=[r31],r17,ar.ccv // try to acquire the lock + // __ticket_spin_trylock(r31) + ld4 r17=[r31] mov r8=EINVAL // default to EINVAL ;; + extr r9=r17,17,15 + ;; + xor r18=r17,r9 + adds r19=1,r17 + ;; + extr.u r18=r18,0,15 + ;; + cmp.eq p0,p7=0,r18 +(p7) br.cond.spnt.many .lock_contention + mov.m ar.ccv=r17 + ;; + cmpxchg4.acq r9=[r31],r19,ar.ccv + ;; + cmp4.eq p0,p7=r9,r17 +(p7) br.cond.spnt.many .lock_contention ld8 r3=[r2] // re-read current->blocked now that we hold the lock - cmp4.ne p6,p0=r18,r0 -(p6) br.cond.spnt.many .lock_contention ;; #else ld8 r3=[r2] // re-read current->blocked now that we hold the lock @@ -490,7 +502,17 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set (p6) br.cond.spnt.few 1b // yes -> retry #ifdef CONFIG_SMP - st4.rel [r31]=r0 // release the lock + // __ticket_spin_unlock(r31) + adds r31=2,r31 + ;; + ld2.bias r2=[r31] + mov r3=65534 + ;; + adds r2=2,r2 + ;; + and r3=r3,r2 + ;; + st2.rel [r31]=r3 #endif SSM_PSR_I(p0, p9, r31) ;; @@ -512,7 +534,17 @@ EX(.fail_efault, (p15) st8 [r34]=r3) .sig_pending: #ifdef CONFIG_SMP - st4.rel [r31]=r0 // release the lock + // __ticket_spin_unlock(r31) + adds r31=2,r31 + ;; + ld2.bias r2=[r31] + mov r3=65534 + ;; + adds r2=2,r2 + ;; + and r3=r3,r2 + ;; + st2.rel [r31]=r3 #endif SSM_PSR_I(p0, p9, r17) ;; -- cgit v1.2.3 From f2c26f52fe46da66b74d6bf818d7941e01eefa04 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Wed, 15 Sep 2010 15:35:48 -0700 Subject: IA64: Optimize ticket spinlocks in fsys_rt_sigprocmask commit 2d2b6901649a62977452be85df53eda2412def24 upstream. Tony's fix (f574c843191728d9407b766a027f779dcd27b272) has a small bug, it incorrectly uses "r3" as a scratch register in the first of the two unlock paths ... it is also inefficient. Optimize the fast path again. Signed-off-by: Petr Tesarik Signed-off-by: Tony Luck Signed-off-by: Greg Kroah-Hartman --- arch/ia64/kernel/fsys.S | 42 +++++++++++------------------------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index 471a1e783aca..331d42bda77a 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S @@ -420,34 +420,31 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set ;; RSM_PSR_I(p0, r18, r19) // mask interrupt delivery - mov ar.ccv=0 andcm r14=r14,r17 // filter out SIGKILL & SIGSTOP + mov r8=EINVAL // default to EINVAL #ifdef CONFIG_SMP // __ticket_spin_trylock(r31) ld4 r17=[r31] - mov r8=EINVAL // default to EINVAL - ;; - extr r9=r17,17,15 ;; - xor r18=r17,r9 + mov.m ar.ccv=r17 + extr.u r9=r17,17,15 adds r19=1,r17 + extr.u r18=r17,0,15 ;; - extr.u r18=r18,0,15 + cmp.eq p6,p7=r9,r18 ;; - cmp.eq p0,p7=0,r18 +(p6) cmpxchg4.acq r9=[r31],r19,ar.ccv +(p6) dep.z r20=r19,1,15 // next serving ticket for unlock (p7) br.cond.spnt.many .lock_contention - mov.m ar.ccv=r17 - ;; - cmpxchg4.acq r9=[r31],r19,ar.ccv ;; cmp4.eq p0,p7=r9,r17 + adds r31=2,r31 (p7) br.cond.spnt.many .lock_contention ld8 r3=[r2] // re-read current->blocked now that we hold the lock ;; #else ld8 r3=[r2] // re-read current->blocked now that we hold the lock - mov r8=EINVAL // default to EINVAL #endif add r18=IA64_TASK_PENDING_OFFSET+IA64_SIGPENDING_SIGNAL_OFFSET,r16 add r19=IA64_TASK_SIGNAL_OFFSET,r16 @@ -503,16 +500,8 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set #ifdef CONFIG_SMP // __ticket_spin_unlock(r31) - adds r31=2,r31 - ;; - ld2.bias r2=[r31] - mov r3=65534 - ;; - adds r2=2,r2 - ;; - and r3=r3,r2 - ;; - st2.rel [r31]=r3 + st2.rel [r31]=r20 + mov r20=0 // i must not leak kernel bits... #endif SSM_PSR_I(p0, p9, r31) ;; @@ -535,16 +524,7 @@ EX(.fail_efault, (p15) st8 [r34]=r3) .sig_pending: #ifdef CONFIG_SMP // __ticket_spin_unlock(r31) - adds r31=2,r31 - ;; - ld2.bias r2=[r31] - mov r3=65534 - ;; - adds r2=2,r2 - ;; - and r3=r3,r2 - ;; - st2.rel [r31]=r3 + st2.rel [r31]=r20 // release the lock #endif SSM_PSR_I(p0, p9, r17) ;; -- cgit v1.2.3 From 21313e0760fd268ca778f54c10b4e8f8e889c97c Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 10 Sep 2010 09:59:46 +0100 Subject: KEYS: Fix RCU no-lock warning in keyctl_session_to_parent() commit 9d1ac65a9698513d00e5608d93fca0c53f536c14 upstream. There's an protected access to the parent process's credentials in the middle of keyctl_session_to_parent(). This results in the following RCU warning: =================================================== [ INFO: suspicious rcu_dereference_check() usage. ] --------------------------------------------------- security/keys/keyctl.c:1291 invoked rcu_dereference_check() without protection! other info that might help us debug this: rcu_scheduler_active = 1, debug_locks = 0 1 lock held by keyctl-session-/2137: #0: (tasklist_lock){.+.+..}, at: [] keyctl_session_to_parent+0x60/0x236 stack backtrace: Pid: 2137, comm: keyctl-session- Not tainted 2.6.36-rc2-cachefs+ #1 Call Trace: [] lockdep_rcu_dereference+0xaa/0xb3 [] keyctl_session_to_parent+0xed/0x236 [] sys_keyctl+0xb4/0xb6 [] system_call_fastpath+0x16/0x1b The code should take the RCU read lock to make sure the parents credentials don't go away, even though it's holding a spinlock and has IRQ disabled. Signed-off-by: David Howells Signed-off-by: Linus Torvalds Cc: dann frazier Signed-off-by: Greg Kroah-Hartman --- security/keys/keyctl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 6261745e4459..747d8f2b5dce 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1259,6 +1259,7 @@ long keyctl_session_to_parent(void) keyring_r = NULL; me = current; + rcu_read_lock(); write_lock_irq(&tasklist_lock); parent = me->real_parent; @@ -1306,6 +1307,7 @@ long keyctl_session_to_parent(void) set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME); write_unlock_irq(&tasklist_lock); + rcu_read_unlock(); if (oldcred) put_cred(oldcred); return 0; @@ -1314,6 +1316,7 @@ already_same: ret = 0; not_permitted: write_unlock_irq(&tasklist_lock); + rcu_read_unlock(); put_cred(cred); return ret; -- cgit v1.2.3 From 0f403655ecddfdb7630adbb6ba59c30cb0c541a4 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 10 Sep 2010 09:59:51 +0100 Subject: KEYS: Fix bug in keyctl_session_to_parent() if parent has no session keyring commit 3d96406c7da1ed5811ea52a3b0905f4f0e295376 upstream. Fix a bug in keyctl_session_to_parent() whereby it tries to check the ownership of the parent process's session keyring whether or not the parent has a session keyring [CVE-2010-2960]. This results in the following oops: BUG: unable to handle kernel NULL pointer dereference at 00000000000000a0 IP: [] keyctl_session_to_parent+0x251/0x443 ... Call Trace: [] ? keyctl_session_to_parent+0x67/0x443 [] ? __do_fault+0x24b/0x3d0 [] sys_keyctl+0xb4/0xb8 [] system_call_fastpath+0x16/0x1b if the parent process has no session keyring. If the system is using pam_keyinit then it mostly protected against this as all processes derived from a login will have inherited the session keyring created by pam_keyinit during the log in procedure. To test this, pam_keyinit calls need to be commented out in /etc/pam.d/. Reported-by: Tavis Ormandy Signed-off-by: David Howells Acked-by: Tavis Ormandy Cc: dann frazier Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- security/keys/keyctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 747d8f2b5dce..e0d1e2b90a21 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1292,7 +1292,8 @@ long keyctl_session_to_parent(void) goto not_permitted; /* the keyrings must have the same UID */ - if (pcred->tgcred->session_keyring->uid != mycred->euid || + if ((pcred->tgcred->session_keyring && + pcred->tgcred->session_keyring->uid != mycred->euid) || mycred->tgcred->session_keyring->uid != mycred->euid) goto not_permitted; -- cgit v1.2.3 From 0d1f22d21f4ca1fe9943667b712beb4d80611236 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Mon, 6 Sep 2010 18:24:57 -0400 Subject: xfs: prevent reading uninitialized stack memory commit a122eb2fdfd78b58c6dd992d6f4b1aaef667eef9 upstream. The XFS_IOC_FSGETXATTR ioctl allows unprivileged users to read 12 bytes of uninitialized stack memory, because the fsxattr struct declared on the stack in xfs_ioc_fsgetxattr() does not alter (or zero) the 12-byte fsx_pad member before copying it back to the user. This patch takes care of it. Signed-off-by: Dan Rosenberg Reviewed-by: Eric Sandeen Signed-off-by: Alex Elder Cc: dann frazier Signed-off-by: Greg Kroah-Hartman --- fs/xfs/linux-2.6/xfs_ioctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index e59a81062830..82a74f6142f8 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -794,6 +794,8 @@ xfs_ioc_fsgetxattr( { struct fsxattr fa; + memset(&fa, 0, sizeof(struct fsxattr)); + xfs_ilock(ip, XFS_ILOCK_SHARED); fa.fsx_xflags = xfs_ip2xflags(ip); fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog; -- cgit v1.2.3 From 63e70525feb93ddfdadd2eb81d0a71a055343d99 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 15 Sep 2010 19:08:24 -0400 Subject: drivers/video/via/ioctl.c: prevent reading uninitialized stack memory commit b4aaa78f4c2f9cde2f335b14f4ca30b01f9651ca upstream. The VIAFB_GET_INFO device ioctl allows unprivileged users to read 246 bytes of uninitialized stack memory, because the "reserved" member of the viafb_ioctl_info struct declared on the stack is not altered or zeroed before being copied back to the user. This patch takes care of it. Signed-off-by: Dan Rosenberg Signed-off-by: Florian Tobias Schandinat Signed-off-by: Greg Kroah-Hartman --- drivers/video/via/ioctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/via/ioctl.c b/drivers/video/via/ioctl.c index da03c074e32a..4d553d0b8d7a 100644 --- a/drivers/video/via/ioctl.c +++ b/drivers/video/via/ioctl.c @@ -25,6 +25,8 @@ int viafb_ioctl_get_viafb_info(u_long arg) { struct viafb_ioctl_info viainfo; + memset(&viainfo, 0, sizeof(struct viafb_ioctl_info)); + viainfo.viafb_id = VIAID; viainfo.vendor_id = PCI_VIA_VENDOR_ID; -- cgit v1.2.3 From bf818d9482431477a787aba2704c8cc48e226703 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Fri, 20 Aug 2010 16:44:33 +0200 Subject: AT91: change dma resource index commit 8d2602e0778299e2d6084f03086b716d6e7a1e1e upstream. Reported-by: Dan Liang Signed-off-by: Nicolas Ferre Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-at91/at91sam9g45_devices.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 809114d5a5a6..501ac6fae2e7 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -46,7 +46,7 @@ static struct resource hdmac_resources[] = { .end = AT91_BASE_SYS + AT91_DMA + SZ_512 - 1, .flags = IORESOURCE_MEM, }, - [2] = { + [1] = { .start = AT91SAM9G45_ID_DMA, .end = AT91SAM9G45_ID_DMA, .flags = IORESOURCE_IRQ, -- cgit v1.2.3 From 2af3495b6359c30740b31175aa818f600f5b8bb9 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 3 Sep 2010 01:24:07 +0200 Subject: PM: Prevent waiting forever on asynchronous resume after failing suspend commit 152e1d592071c8b312bb898bc1118b64e4aea535 upstream. During suspend, the power.completion is expected to be set when a device has not yet started suspending. Set it on init to fix a corner case where a device is resumed when its parent has never suspended. Consider three drivers, A, B, and C. The parent of A is C, and C has async_suspend set. On boot, C->power.completion is initialized to 0. During the first suspend: suspend_devices_and_enter(...) dpm_resume(...) device_suspend(A) device_suspend(B) returns error, aborts suspend dpm_resume_end(...) dpm_resume(...) device_resume(A) dpm_wait(A->parent == C) wait_for_completion(C->power.completion) The wait_for_completion will never complete, because complete_all(C->power.completion) will only be called from device_suspend(C) or device_resume(C), neither of which is called if suspend is aborted before C. After a successful suspend->resume cycle, where B doesn't abort suspend, C->power.completion is left in the completed state by the call to device_resume(C), and the same call path will work if B aborts suspend. Signed-off-by: Colin Cross Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 941fcb87e52a..cb1cedc69c9b 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -59,6 +59,7 @@ void device_pm_init(struct device *dev) { dev->power.status = DPM_ON; init_completion(&dev->power.completion); + complete_all(&dev->power.completion); pm_runtime_init(dev); } -- cgit v1.2.3 From ff278af4dcda812b4a3f8ef0d0260232ed1352ac Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 11 Sep 2010 20:58:27 +0200 Subject: PM / Hibernate: Avoid hitting OOM during preallocation of memory commit 6715045ddc7472a22be5e49d4047d2d89b391f45 upstream. There is a problem in hibernate_preallocate_memory() that it calls preallocate_image_memory() with an argument that may be greater than the total number of available non-highmem memory pages. If that's the case, the OOM condition is guaranteed to trigger, which in turn can cause significant slowdown to occur during hibernation. To avoid that, make preallocate_image_memory() adjust its argument before calling preallocate_image_pages(), so that the total number of saveable non-highem pages left is not less than the minimum size of a hibernation image. Change hibernate_preallocate_memory() to try to allocate from highmem if the number of pages allocated by preallocate_image_memory() is too low. Modify free_unnecessary_pages() to take all possible memory allocation patterns into account. Reported-by: KOSAKI Motohiro Signed-off-by: Rafael J. Wysocki Tested-by: M. Vefa Bicakci Signed-off-by: Greg Kroah-Hartman --- kernel/power/snapshot.c | 85 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 20 deletions(-) diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 25ce010e9f8b..7fa52b5ce88d 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -1121,9 +1121,19 @@ static unsigned long preallocate_image_pages(unsigned long nr_pages, gfp_t mask) return nr_alloc; } -static unsigned long preallocate_image_memory(unsigned long nr_pages) +static unsigned long preallocate_image_memory(unsigned long nr_pages, + unsigned long avail_normal) { - return preallocate_image_pages(nr_pages, GFP_IMAGE); + unsigned long alloc; + + if (avail_normal <= alloc_normal) + return 0; + + alloc = avail_normal - alloc_normal; + if (nr_pages < alloc) + alloc = nr_pages; + + return preallocate_image_pages(alloc, GFP_IMAGE); } #ifdef CONFIG_HIGHMEM @@ -1169,15 +1179,22 @@ static inline unsigned long preallocate_highmem_fraction(unsigned long nr_pages, */ static void free_unnecessary_pages(void) { - unsigned long save_highmem, to_free_normal, to_free_highmem; + unsigned long save, to_free_normal, to_free_highmem; - to_free_normal = alloc_normal - count_data_pages(); - save_highmem = count_highmem_pages(); - if (alloc_highmem > save_highmem) { - to_free_highmem = alloc_highmem - save_highmem; + save = count_data_pages(); + if (alloc_normal >= save) { + to_free_normal = alloc_normal - save; + save = 0; + } else { + to_free_normal = 0; + save -= alloc_normal; + } + save += count_highmem_pages(); + if (alloc_highmem >= save) { + to_free_highmem = alloc_highmem - save; } else { to_free_highmem = 0; - to_free_normal -= save_highmem - alloc_highmem; + to_free_normal -= save - alloc_highmem; } memory_bm_position_reset(©_bm); @@ -1258,7 +1275,7 @@ int hibernate_preallocate_memory(void) { struct zone *zone; unsigned long saveable, size, max_size, count, highmem, pages = 0; - unsigned long alloc, save_highmem, pages_highmem; + unsigned long alloc, save_highmem, pages_highmem, avail_normal; struct timeval start, stop; int error; @@ -1295,6 +1312,7 @@ int hibernate_preallocate_memory(void) else count += zone_page_state(zone, NR_FREE_PAGES); } + avail_normal = count; count += highmem; count -= totalreserve_pages; @@ -1309,12 +1327,21 @@ int hibernate_preallocate_memory(void) */ if (size >= saveable) { pages = preallocate_image_highmem(save_highmem); - pages += preallocate_image_memory(saveable - pages); + pages += preallocate_image_memory(saveable - pages, avail_normal); goto out; } /* Estimate the minimum size of the image. */ pages = minimum_image_size(saveable); + /* + * To avoid excessive pressure on the normal zone, leave room in it to + * accommodate an image of the minimum size (unless it's already too + * small, in which case don't preallocate pages from it at all). + */ + if (avail_normal > pages) + avail_normal -= pages; + else + avail_normal = 0; if (size < pages) size = min_t(unsigned long, pages, max_size); @@ -1335,16 +1362,34 @@ int hibernate_preallocate_memory(void) */ pages_highmem = preallocate_image_highmem(highmem / 2); alloc = (count - max_size) - pages_highmem; - pages = preallocate_image_memory(alloc); - if (pages < alloc) - goto err_out; - size = max_size - size; - alloc = size; - size = preallocate_highmem_fraction(size, highmem, count); - pages_highmem += size; - alloc -= size; - pages += preallocate_image_memory(alloc); - pages += pages_highmem; + pages = preallocate_image_memory(alloc, avail_normal); + if (pages < alloc) { + /* We have exhausted non-highmem pages, try highmem. */ + alloc -= pages; + pages += pages_highmem; + pages_highmem = preallocate_image_highmem(alloc); + if (pages_highmem < alloc) + goto err_out; + pages += pages_highmem; + /* + * size is the desired number of saveable pages to leave in + * memory, so try to preallocate (all memory - size) pages. + */ + alloc = (count - pages) - size; + pages += preallocate_image_highmem(alloc); + } else { + /* + * There are approximately max_size saveable pages at this point + * and we want to reduce this number down to size. + */ + alloc = max_size - size; + size = preallocate_highmem_fraction(alloc, highmem, count); + pages_highmem += size; + alloc -= size; + size = preallocate_image_memory(alloc, avail_normal); + pages_highmem += preallocate_image_highmem(alloc - size); + pages += pages_highmem + size; + } /* * We only need as many page frames for the image as there are saveable -- cgit v1.2.3 From 24dadf6e9439a4599fb8afeb243930dcc5883ffa Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Thu, 12 Aug 2010 07:00:35 -0700 Subject: x86, asm: Use a lower case name for the end macro in atomic64_386_32.S commit 417484d47e115774745ef025bce712a102b6f86f upstream. Use a lowercase name for the end macro, which somehow fixes a binutils 2.16 problem. Signed-off-by: Luca Barbieri LKML-Reference: Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/lib/atomic64_386_32.S | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/arch/x86/lib/atomic64_386_32.S b/arch/x86/lib/atomic64_386_32.S index 78ee8e0fa278..2cda60a06e65 100644 --- a/arch/x86/lib/atomic64_386_32.S +++ b/arch/x86/lib/atomic64_386_32.S @@ -26,35 +26,37 @@ .endm #define BEGIN(op) \ -.macro END; \ +.macro endp; \ CFI_ENDPROC; \ ENDPROC(atomic64_##op##_386); \ -.purgem END; \ +.purgem endp; \ .endm; \ ENTRY(atomic64_##op##_386); \ CFI_STARTPROC; \ LOCK v; +#define ENDP endp + #define RET \ UNLOCK v; \ ret -#define RET_END \ +#define RET_ENDP \ RET; \ - END + ENDP #define v %ecx BEGIN(read) movl (v), %eax movl 4(v), %edx -RET_END +RET_ENDP #undef v #define v %esi BEGIN(set) movl %ebx, (v) movl %ecx, 4(v) -RET_END +RET_ENDP #undef v #define v %esi @@ -63,14 +65,14 @@ BEGIN(xchg) movl 4(v), %edx movl %ebx, (v) movl %ecx, 4(v) -RET_END +RET_ENDP #undef v #define v %ecx BEGIN(add) addl %eax, (v) adcl %edx, 4(v) -RET_END +RET_ENDP #undef v #define v %ecx @@ -79,14 +81,14 @@ BEGIN(add_return) adcl 4(v), %edx movl %eax, (v) movl %edx, 4(v) -RET_END +RET_ENDP #undef v #define v %ecx BEGIN(sub) subl %eax, (v) sbbl %edx, 4(v) -RET_END +RET_ENDP #undef v #define v %ecx @@ -98,14 +100,14 @@ BEGIN(sub_return) adcl 4(v), %edx movl %eax, (v) movl %edx, 4(v) -RET_END +RET_ENDP #undef v #define v %esi BEGIN(inc) addl $1, (v) adcl $0, 4(v) -RET_END +RET_ENDP #undef v #define v %esi @@ -116,14 +118,14 @@ BEGIN(inc_return) adcl $0, %edx movl %eax, (v) movl %edx, 4(v) -RET_END +RET_ENDP #undef v #define v %esi BEGIN(dec) subl $1, (v) sbbl $0, 4(v) -RET_END +RET_ENDP #undef v #define v %esi @@ -134,7 +136,7 @@ BEGIN(dec_return) sbbl $0, %edx movl %eax, (v) movl %edx, 4(v) -RET_END +RET_ENDP #undef v #define v %ecx @@ -156,7 +158,7 @@ BEGIN(add_unless) jne 1b xorl %eax, %eax jmp 2b -END +ENDP #undef v #define v %esi @@ -177,7 +179,7 @@ BEGIN(inc_not_zero) testl %edx, %edx jne 1b jmp 2b -END +ENDP #undef v #define v %esi @@ -190,5 +192,5 @@ BEGIN(dec_if_positive) movl %eax, (v) movl %edx, 4(v) 1: -RET_END +RET_ENDP #undef v -- cgit v1.2.3 From 013dbea410981f6a064d1e7b2abfcbbbe6d24c9c Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Tue, 3 Aug 2010 11:09:13 +0100 Subject: ALSA: hda - Fix beep frequency on IDT 92HD73xx and 92HD71Bxx codecs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 1b0e372d7b52c9fc96348779015a6db7df7f286e upstream. Fix HDA beep frequency on IDT 92HD73xx and 92HD71Bxx codecs. These codecs use the standard beep frequency calculation although the datasheet says it's linear frequency. Other IDT/STAC codecs might have the same problem. They should be fixed individually later. Signed-off-by: Daniel J Blueman Signed-off-by: Takashi Iwai Cc: أحمد المحمودي Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_sigmatel.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index f1e7babd6920..b8d730c47df1 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -202,6 +202,7 @@ struct sigmatel_spec { unsigned int spdif_mute: 1; unsigned int check_volume_offset:1; unsigned int auto_mic:1; + unsigned int linear_tone_beep:1; /* gpio lines */ unsigned int eapd_mask; @@ -3802,7 +3803,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out return err; if (codec->beep) { /* IDT/STAC codecs have linear beep tone parameter */ - codec->beep->linear_tone = 1; + codec->beep->linear_tone = spec->linear_tone_beep; /* if no beep switch is available, make its own one */ caps = query_amp_caps(codec, nid, HDA_OUTPUT); if (!(caps & AC_AMPCAP_MUTE)) { @@ -5005,6 +5006,7 @@ static int patch_stac9200(struct hda_codec *codec) codec->no_trigger_sense = 1; codec->spec = spec; + spec->linear_tone_beep = 1; spec->num_pins = ARRAY_SIZE(stac9200_pin_nids); spec->pin_nids = stac9200_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, @@ -5068,6 +5070,7 @@ static int patch_stac925x(struct hda_codec *codec) codec->no_trigger_sense = 1; codec->spec = spec; + spec->linear_tone_beep = 1; spec->num_pins = ARRAY_SIZE(stac925x_pin_nids); spec->pin_nids = stac925x_pin_nids; @@ -5153,6 +5156,7 @@ static int patch_stac92hd73xx(struct hda_codec *codec) codec->no_trigger_sense = 1; codec->spec = spec; + spec->linear_tone_beep = 0; codec->slave_dig_outs = stac92hd73xx_slave_dig_outs; spec->num_pins = ARRAY_SIZE(stac92hd73xx_pin_nids); spec->pin_nids = stac92hd73xx_pin_nids; @@ -5300,6 +5304,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) codec->no_trigger_sense = 1; codec->spec = spec; + spec->linear_tone_beep = 1; codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; spec->digbeep_nid = 0x21; spec->mux_nids = stac92hd83xxx_mux_nids; @@ -5522,6 +5527,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) codec->no_trigger_sense = 1; codec->spec = spec; + spec->linear_tone_beep = 0; codec->patch_ops = stac92xx_patch_ops; spec->num_pins = STAC92HD71BXX_NUM_PINS; switch (codec->vendor_id) { @@ -5779,6 +5785,7 @@ static int patch_stac922x(struct hda_codec *codec) codec->no_trigger_sense = 1; codec->spec = spec; + spec->linear_tone_beep = 1; spec->num_pins = ARRAY_SIZE(stac922x_pin_nids); spec->pin_nids = stac922x_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS, @@ -5883,6 +5890,7 @@ static int patch_stac927x(struct hda_codec *codec) codec->no_trigger_sense = 1; codec->spec = spec; + spec->linear_tone_beep = 1; codec->slave_dig_outs = stac927x_slave_dig_outs; spec->num_pins = ARRAY_SIZE(stac927x_pin_nids); spec->pin_nids = stac927x_pin_nids; @@ -6018,6 +6026,7 @@ static int patch_stac9205(struct hda_codec *codec) codec->no_trigger_sense = 1; codec->spec = spec; + spec->linear_tone_beep = 1; spec->num_pins = ARRAY_SIZE(stac9205_pin_nids); spec->pin_nids = stac9205_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS, @@ -6174,6 +6183,7 @@ static int patch_stac9872(struct hda_codec *codec) return -ENOMEM; codec->no_trigger_sense = 1; codec->spec = spec; + spec->linear_tone_beep = 1; spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); spec->pin_nids = stac9872_pin_nids; -- cgit v1.2.3 From 92e8e73dcc82076d63296c03700a3d6324672028 Mon Sep 17 00:00:00 2001 From: "Morten H. Larsen" Date: Tue, 31 Aug 2010 22:29:13 -0400 Subject: Fix call to replaced SuperIO functions commit 59b25ed91400ace98d6cf0d59b1cb6928ad5cd37 upstream. This patch fixes the failure to compile Alpha Generic because of previously overlooked calls to ns87312_enable_ide(). The function has been replaced by newer SuperIO code. Tested-by: Michael Cree Signed-off-by: Morten H. Larsen Signed-off-by: Matt Turner Signed-off-by: Greg Kroah-Hartman --- arch/alpha/kernel/proto.h | 3 --- arch/alpha/kernel/sys_cabriolet.c | 19 ++++++++++++++++--- arch/alpha/kernel/sys_takara.c | 11 +++++++++-- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h index 3d2627ec9860..d3e52d3fd592 100644 --- a/arch/alpha/kernel/proto.h +++ b/arch/alpha/kernel/proto.h @@ -156,9 +156,6 @@ extern void SMC669_Init(int); /* es1888.c */ extern void es1888_init(void); -/* ns87312.c */ -extern void ns87312_enable_ide(long ide_base); - /* ../lib/fpreg.c */ extern void alpha_write_fp_reg (unsigned long reg, unsigned long val); extern unsigned long alpha_read_fp_reg (unsigned long reg); diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c index affd0f3f25df..14c8898d19ec 100644 --- a/arch/alpha/kernel/sys_cabriolet.c +++ b/arch/alpha/kernel/sys_cabriolet.c @@ -33,7 +33,7 @@ #include "irq_impl.h" #include "pci_impl.h" #include "machvec_impl.h" - +#include "pc873xx.h" /* Note mask bit is true for DISABLED irqs. */ static unsigned long cached_irq_mask = ~0UL; @@ -235,18 +235,31 @@ cabriolet_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return COMMON_TABLE_LOOKUP; } +static inline void __init +cabriolet_enable_ide(void) +{ + if (pc873xx_probe() == -1) { + printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n"); + } else { + printk(KERN_INFO "Found %s Super IO chip at 0x%x\n", + pc873xx_get_model(), pc873xx_get_base()); + + pc873xx_enable_ide(); + } +} + static inline void __init cabriolet_init_pci(void) { common_init_pci(); - ns87312_enable_ide(0x398); + cabriolet_enable_ide(); } static inline void __init cia_cab_init_pci(void) { cia_init_pci(); - ns87312_enable_ide(0x398); + cabriolet_enable_ide(); } /* diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c index 230464885b5c..4da596b6adbb 100644 --- a/arch/alpha/kernel/sys_takara.c +++ b/arch/alpha/kernel/sys_takara.c @@ -29,7 +29,7 @@ #include "irq_impl.h" #include "pci_impl.h" #include "machvec_impl.h" - +#include "pc873xx.h" /* Note mask bit is true for DISABLED irqs. */ static unsigned long cached_irq_mask[2] = { -1, -1 }; @@ -264,7 +264,14 @@ takara_init_pci(void) alpha_mv.pci_map_irq = takara_map_irq_srm; cia_init_pci(); - ns87312_enable_ide(0x26e); + + if (pc873xx_probe() == -1) { + printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n"); + } else { + printk(KERN_INFO "Found %s Super IO chip at 0x%x\n", + pc873xx_get_model(), pc873xx_get_base()); + pc873xx_enable_ide(); + } } -- cgit v1.2.3 From 221d4da7cbe3a3a66d2adc0d7bb91a1d92d8c0bb Mon Sep 17 00:00:00 2001 From: Islam Amer Date: Thu, 24 Jun 2010 13:39:47 -0400 Subject: dell-wmi: Add support for eject key on Dell Studio 1555 commit d5164dbf1f651d1e955b158fb70a9c844cc91cd1 upstream. Fixes pressing the eject key on Dell Studio 1555 does not work and produces message : dell-wmi: Unknown key 0 pressed Signed-off-by: Islam Amer Cc: Kyle McMartin Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/dell-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 66f53c3c35e8..12a8e6fa1d56 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -221,7 +221,7 @@ static void dell_wmi_notify(u32 value, void *context) return; } - if (dell_new_hk_type) + if (dell_new_hk_type || buffer_entry[1] == 0x0) reported_key = (int)buffer_entry[2]; else reported_key = (int)buffer_entry[1] & 0xffff; -- cgit v1.2.3 From 39f7a62c0d15eb8b489a707778e9c8c30d7f4d5d Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Thu, 9 Sep 2010 16:38:18 -0700 Subject: mm: page allocator: drain per-cpu lists after direct reclaim allocation fails commit 9ee493ce0a60bf42c0f8fd0b0fe91df5704a1cbf upstream. When under significant memory pressure, a process enters direct reclaim and immediately afterwards tries to allocate a page. If it fails and no further progress is made, it's possible the system will go OOM. However, on systems with large amounts of memory, it's possible that a significant number of pages are on per-cpu lists and inaccessible to the calling process. This leads to a process entering direct reclaim more often than it should increasing the pressure on the system and compounding the problem. This patch notes that if direct reclaim is making progress but allocations are still failing that the system is already under heavy pressure. In this case, it drains the per-cpu lists and tries the allocation a second time before continuing. Signed-off-by: Mel Gorman Reviewed-by: Minchan Kim Reviewed-by: KAMEZAWA Hiroyuki Reviewed-by: KOSAKI Motohiro Reviewed-by: Christoph Lameter Cc: Dave Chinner Cc: Wu Fengguang Cc: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/page_alloc.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 9bd339eb04c6..66008d7eeb86 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1843,6 +1843,7 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order, struct page *page = NULL; struct reclaim_state reclaim_state; struct task_struct *p = current; + bool drained = false; cond_resched(); @@ -1861,14 +1862,25 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order, cond_resched(); - if (order != 0) - drain_all_pages(); + if (unlikely(!(*did_some_progress))) + return NULL; - if (likely(*did_some_progress)) - page = get_page_from_freelist(gfp_mask, nodemask, order, +retry: + page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist, high_zoneidx, alloc_flags, preferred_zone, migratetype); + + /* + * If an allocation failed after direct reclaim, it could be because + * pages are pinned on the per-cpu lists. Drain them and try again + */ + if (!page && !drained) { + drain_all_pages(); + drained = true; + goto retry; + } + return page; } -- cgit v1.2.3 From 87f1cbdee91c60af6dd255226e792a6410d77fbb Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Thu, 9 Sep 2010 16:38:17 -0700 Subject: mm: page allocator: calculate a better estimate of NR_FREE_PAGES when memory is low and kswapd is awake commit aa45484031ddee09b06350ab8528bfe5b2c76d1c upstream. Ordinarily watermark checks are based on the vmstat NR_FREE_PAGES as it is cheaper than scanning a number of lists. To avoid synchronization overhead, counter deltas are maintained on a per-cpu basis and drained both periodically and when the delta is above a threshold. On large CPU systems, the difference between the estimated and real value of NR_FREE_PAGES can be very high. If NR_FREE_PAGES is much higher than number of real free page in buddy, the VM can allocate pages below min watermark, at worst reducing the real number of pages to zero. Even if the OOM killer kills some victim for freeing memory, it may not free memory if the exit path requires a new page resulting in livelock. This patch introduces a zone_page_state_snapshot() function (courtesy of Christoph) that takes a slightly more accurate view of an arbitrary vmstat counter. It is used to read NR_FREE_PAGES while kswapd is awake to avoid the watermark being accidentally broken. The estimate is not perfect and may result in cache line bounces but is expected to be lighter than the IPI calls necessary to continually drain the per-cpu counters while kswapd is awake. Signed-off-by: Christoph Lameter Signed-off-by: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/mmzone.h | 13 +++++++++++++ include/linux/vmstat.h | 22 ++++++++++++++++++++++ mm/mmzone.c | 21 +++++++++++++++++++++ mm/page_alloc.c | 4 ++-- mm/vmstat.c | 15 ++++++++++++++- 5 files changed, 72 insertions(+), 3 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index b4d109e389b8..8b2db3d65564 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -283,6 +283,13 @@ struct zone { /* zone watermarks, access with *_wmark_pages(zone) macros */ unsigned long watermark[NR_WMARK]; + /* + * When free pages are below this point, additional steps are taken + * when reading the number of free pages to avoid per-cpu counter + * drift allowing watermarks to be breached + */ + unsigned long percpu_drift_mark; + /* * We don't know if the memory that we're going to allocate will be freeable * or/and it will be released eventually, so to avoid totally wasting several @@ -456,6 +463,12 @@ static inline int zone_is_oom_locked(const struct zone *zone) return test_bit(ZONE_OOM_LOCKED, &zone->flags); } +#ifdef CONFIG_SMP +unsigned long zone_nr_free_pages(struct zone *zone); +#else +#define zone_nr_free_pages(zone) zone_page_state(zone, NR_FREE_PAGES) +#endif /* CONFIG_SMP */ + /* * The "priority" of VM scanning is how much of the queues we will scan in one * go. A value of 12 for DEF_PRIORITY implies that we will scan 1/4096th of the diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h index 7f43ccdc1d38..eaaea37b3b75 100644 --- a/include/linux/vmstat.h +++ b/include/linux/vmstat.h @@ -170,6 +170,28 @@ static inline unsigned long zone_page_state(struct zone *zone, return x; } +/* + * More accurate version that also considers the currently pending + * deltas. For that we need to loop over all cpus to find the current + * deltas. There is no synchronization so the result cannot be + * exactly accurate either. + */ +static inline unsigned long zone_page_state_snapshot(struct zone *zone, + enum zone_stat_item item) +{ + long x = atomic_long_read(&zone->vm_stat[item]); + +#ifdef CONFIG_SMP + int cpu; + for_each_online_cpu(cpu) + x += per_cpu_ptr(zone->pageset, cpu)->vm_stat_diff[item]; + + if (x < 0) + x = 0; +#endif + return x; +} + extern unsigned long global_reclaimable_pages(void); extern unsigned long zone_reclaimable_pages(struct zone *zone); diff --git a/mm/mmzone.c b/mm/mmzone.c index f5b7d1760213..e35bfb82c855 100644 --- a/mm/mmzone.c +++ b/mm/mmzone.c @@ -87,3 +87,24 @@ int memmap_valid_within(unsigned long pfn, return 1; } #endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */ + +#ifdef CONFIG_SMP +/* Called when a more accurate view of NR_FREE_PAGES is needed */ +unsigned long zone_nr_free_pages(struct zone *zone) +{ + unsigned long nr_free_pages = zone_page_state(zone, NR_FREE_PAGES); + + /* + * While kswapd is awake, it is considered the zone is under some + * memory pressure. Under pressure, there is a risk that + * per-cpu-counter-drift will allow the min watermark to be breached + * potentially causing a live-lock. While kswapd is awake and + * free pages are low, get a better estimate for free pages + */ + if (nr_free_pages < zone->percpu_drift_mark && + !waitqueue_active(&zone->zone_pgdat->kswapd_wait)) + return zone_page_state_snapshot(zone, NR_FREE_PAGES); + + return nr_free_pages; +} +#endif /* CONFIG_SMP */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 66008d7eeb86..89d9ac556325 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1461,7 +1461,7 @@ int zone_watermark_ok(struct zone *z, int order, unsigned long mark, { /* free_pages my go negative - that's OK */ long min = mark; - long free_pages = zone_page_state(z, NR_FREE_PAGES) - (1 << order) + 1; + long free_pages = zone_nr_free_pages(z) - (1 << order) + 1; int o; if (alloc_flags & ALLOC_HIGH) @@ -2424,7 +2424,7 @@ void show_free_areas(void) " all_unreclaimable? %s" "\n", zone->name, - K(zone_page_state(zone, NR_FREE_PAGES)), + K(zone_nr_free_pages(zone)), K(min_wmark_pages(zone)), K(low_wmark_pages(zone)), K(high_wmark_pages(zone)), diff --git a/mm/vmstat.c b/mm/vmstat.c index 7759941d4e77..26d5716b1fce 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -138,11 +138,24 @@ static void refresh_zone_stat_thresholds(void) int threshold; for_each_populated_zone(zone) { + unsigned long max_drift, tolerate_drift; + threshold = calculate_threshold(zone); for_each_online_cpu(cpu) per_cpu_ptr(zone->pageset, cpu)->stat_threshold = threshold; + + /* + * Only set percpu_drift_mark if there is a danger that + * NR_FREE_PAGES reports the low watermark is ok when in fact + * the min watermark could be breached by an allocation + */ + tolerate_drift = low_wmark_pages(zone) - min_wmark_pages(zone); + max_drift = num_online_cpus() * threshold; + if (max_drift > tolerate_drift) + zone->percpu_drift_mark = high_wmark_pages(zone) + + max_drift; } } @@ -813,7 +826,7 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat, "\n scanned %lu" "\n spanned %lu" "\n present %lu", - zone_page_state(zone, NR_FREE_PAGES), + zone_nr_free_pages(zone), min_wmark_pages(zone), low_wmark_pages(zone), high_wmark_pages(zone), -- cgit v1.2.3 From 3c8b7588c8bb9609c73c49087449be991d3d45ba Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Thu, 9 Sep 2010 16:38:16 -0700 Subject: mm: page allocator: update free page counters after pages are placed on the free list commit 72853e2991a2702ae93aaf889ac7db743a415dd3 upstream. When allocating a page, the system uses NR_FREE_PAGES counters to determine if watermarks would remain intact after the allocation was made. This check is made without interrupts disabled or the zone lock held and so is race-prone by nature. Unfortunately, when pages are being freed in batch, the counters are updated before the pages are added on the list. During this window, the counters are misleading as the pages do not exist yet. When under significant pressure on systems with large numbers of CPUs, it's possible for processes to make progress even though they should have been stalled. This is particularly problematic if a number of the processes are using GFP_ATOMIC as the min watermark can be accidentally breached and in extreme cases, the system can livelock. This patch updates the counters after the pages have been added to the list. This makes the allocator more cautious with respect to preserving the watermarks and mitigates livelock possibilities. [akpm@linux-foundation.org: avoid modifying incoming args] Signed-off-by: Mel Gorman Reviewed-by: Rik van Riel Reviewed-by: Minchan Kim Reviewed-by: KAMEZAWA Hiroyuki Reviewed-by: Christoph Lameter Reviewed-by: KOSAKI Motohiro Acked-by: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/page_alloc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 89d9ac556325..f7cc624085cc 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -588,13 +588,13 @@ static void free_pcppages_bulk(struct zone *zone, int count, { int migratetype = 0; int batch_free = 0; + int to_free = count; spin_lock(&zone->lock); zone->all_unreclaimable = 0; zone->pages_scanned = 0; - __mod_zone_page_state(zone, NR_FREE_PAGES, count); - while (count) { + while (to_free) { struct page *page; struct list_head *list; @@ -619,8 +619,9 @@ static void free_pcppages_bulk(struct zone *zone, int count, /* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */ __free_one_page(page, zone, 0, page_private(page)); trace_mm_page_pcpu_drain(page, 0, page_private(page)); - } while (--count && --batch_free && !list_empty(list)); + } while (--to_free && --batch_free && !list_empty(list)); } + __mod_zone_page_state(zone, NR_FREE_PAGES, count); spin_unlock(&zone->lock); } @@ -631,8 +632,8 @@ static void free_one_page(struct zone *zone, struct page *page, int order, zone->all_unreclaimable = 0; zone->pages_scanned = 0; - __mod_zone_page_state(zone, NR_FREE_PAGES, 1 << order); __free_one_page(page, zone, order, migratetype); + __mod_zone_page_state(zone, NR_FREE_PAGES, 1 << order); spin_unlock(&zone->lock); } -- cgit v1.2.3 From 0ac99e6ff81f5c4d57c2cb1b716a3cb78227740c Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Tue, 24 Aug 2010 11:44:18 -0700 Subject: guard page for stacks that grow upwards commit 8ca3eb08097f6839b2206e2242db4179aee3cfb3 upstream. pa-risc and ia64 have stacks that grow upwards. Check that they do not run into other mappings. By making VM_GROWSUP 0x0 on architectures that do not ever use it, we can avoid some unpleasant #ifdefs in check_stack_guard_page(). Signed-off-by: Tony Luck Signed-off-by: Linus Torvalds Cc: dann frazier Signed-off-by: Greg Kroah-Hartman --- include/linux/mm.h | 8 +++++++- mm/memory.c | 15 +++++++++++---- mm/mmap.c | 3 --- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index a2b48041b910..c1f54d2c63d0 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -78,7 +78,11 @@ extern unsigned int kobjsize(const void *objp); #define VM_MAYSHARE 0x00000080 #define VM_GROWSDOWN 0x00000100 /* general info on the segment */ +#if defined(CONFIG_STACK_GROWSUP) || defined(CONFIG_IA64) #define VM_GROWSUP 0x00000200 +#else +#define VM_GROWSUP 0x00000000 +#endif #define VM_PFNMAP 0x00000400 /* Page-ranges managed without "struct page", just pure PFN */ #define VM_DENYWRITE 0x00000800 /* ETXTBSY on write attempts.. */ @@ -1329,8 +1333,10 @@ unsigned long ra_submit(struct file_ra_state *ra, /* Do stack extension */ extern int expand_stack(struct vm_area_struct *vma, unsigned long address); -#ifdef CONFIG_IA64 +#if VM_GROWSUP extern int expand_upwards(struct vm_area_struct *vma, unsigned long address); +#else + #define expand_upwards(vma, address) do { } while (0) #endif extern int expand_stack_downwards(struct vm_area_struct *vma, unsigned long address); diff --git a/mm/memory.c b/mm/memory.c index 93da8f1338c4..7550758d26f8 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2791,11 +2791,9 @@ out_release: } /* - * This is like a special single-page "expand_downwards()", - * except we must first make sure that 'address-PAGE_SIZE' + * This is like a special single-page "expand_{down|up}wards()", + * except we must first make sure that 'address{-|+}PAGE_SIZE' * doesn't hit another vma. - * - * The "find_vma()" will do the right thing even if we wrap */ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address) { @@ -2814,6 +2812,15 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo expand_stack(vma, address - PAGE_SIZE); } + if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) { + struct vm_area_struct *next = vma->vm_next; + + /* As VM_GROWSDOWN but s/below/above/ */ + if (next && next->vm_start == address + PAGE_SIZE) + return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM; + + expand_upwards(vma, address + PAGE_SIZE); + } return 0; } diff --git a/mm/mmap.c b/mm/mmap.c index 12d38bf4f5b0..3a943622bd9a 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1704,9 +1704,6 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns * PA-RISC uses this for its stack; IA64 for its Register Backing Store. * vma is the last one with address > vma->vm_end. Have to extend vma. */ -#ifndef CONFIG_IA64 -static -#endif int expand_upwards(struct vm_area_struct *vma, unsigned long address) { int error; -- cgit v1.2.3 From 2178c26dbdca2ac63c0e4183aa9e570e2ffe593e Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Tue, 17 Aug 2010 23:56:55 +0100 Subject: Fix unprotected access to task credentials in waitid() commit f362b73244fb16ea4ae127ced1467dd8adaa7733 upstream. Using a program like the following: #include #include #include #include int main() { id_t id; siginfo_t infop; pid_t res; id = fork(); if (id == 0) { sleep(1); exit(0); } kill(id, SIGSTOP); alarm(1); waitid(P_PID, id, &infop, WCONTINUED); return 0; } to call waitid() on a stopped process results in access to the child task's credentials without the RCU read lock being held - which may be replaced in the meantime - eliciting the following warning: =================================================== [ INFO: suspicious rcu_dereference_check() usage. ] --------------------------------------------------- kernel/exit.c:1460 invoked rcu_dereference_check() without protection! other info that might help us debug this: rcu_scheduler_active = 1, debug_locks = 1 2 locks held by waitid02/22252: #0: (tasklist_lock){.?.?..}, at: [] do_wait+0xc5/0x310 #1: (&(&sighand->siglock)->rlock){-.-...}, at: [] wait_consider_task+0x19a/0xbe0 stack backtrace: Pid: 22252, comm: waitid02 Not tainted 2.6.35-323cd+ #3 Call Trace: [] lockdep_rcu_dereference+0xa4/0xc0 [] wait_consider_task+0xaf1/0xbe0 [] do_wait+0xf5/0x310 [] sys_waitid+0x86/0x1f0 [] ? child_wait_callback+0x0/0x70 [] system_call_fastpath+0x16/0x1b This is fixed by holding the RCU read lock in wait_task_continued() to ensure that the task's current credentials aren't destroyed between us reading the cred pointer and us reading the UID from those credentials. Furthermore, protect wait_task_stopped() in the same way. We don't need to keep holding the RCU read lock once we've read the UID from the credentials as holding the RCU read lock doesn't stop the target task from changing its creds under us - so the credentials may be outdated immediately after we've read the pointer, lock or no lock. Signed-off-by: Daniel J Blueman Signed-off-by: David Howells Acked-by: Paul E. McKenney Acked-by: Oleg Nesterov Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/exit.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/kernel/exit.c b/kernel/exit.c index ceffc67b564a..ac90425ce996 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -1383,8 +1383,7 @@ static int wait_task_stopped(struct wait_opts *wo, if (!unlikely(wo->wo_flags & WNOWAIT)) *p_code = 0; - /* don't need the RCU readlock here as we're holding a spinlock */ - uid = __task_cred(p)->uid; + uid = task_uid(p); unlock_sig: spin_unlock_irq(&p->sighand->siglock); if (!exit_code) @@ -1457,7 +1456,7 @@ static int wait_task_continued(struct wait_opts *wo, struct task_struct *p) } if (!unlikely(wo->wo_flags & WNOWAIT)) p->signal->flags &= ~SIGNAL_STOP_CONTINUED; - uid = __task_cred(p)->uid; + uid = task_uid(p); spin_unlock_irq(&p->sighand->siglock); pid = task_pid_vnr(p); -- cgit v1.2.3 From 21a32e679ffa7491e89bfbefa0d36413ca9cb64c Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Wed, 15 Sep 2010 10:00:26 -0400 Subject: sctp: Do not reset the packet during sctp_packet_config(). commit 4bdab43323b459900578b200a4b8cf9713ac8fab upstream. sctp_packet_config() is called when getting the packet ready for appending of chunks. The function should not touch the current state, since it's possible to ping-pong between two transports when sending, and that can result packet corruption followed by skb overlfow crash. Reported-by: Thomas Dreibholz Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sctp/output.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/sctp/output.c b/net/sctp/output.c index a646681f5acd..bcc4590ccaf2 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -92,7 +92,6 @@ struct sctp_packet *sctp_packet_config(struct sctp_packet *packet, SCTP_DEBUG_PRINTK("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag); - sctp_packet_reset(packet); packet->vtag = vtag; if (ecn_capable && sctp_packet_empty(packet)) { -- cgit v1.2.3 From ae043da9f41d0e020eec1c8888337e7e7012eae2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 12 Sep 2010 18:25:19 +0100 Subject: drm/i915: Ensure that the crtcinfo is populated during mode_fixup() commit 897493504addc5609f04a2c4f73c37ab972c29b2 upstream. This should fix the mysterious mode setting failures reported during boot up and after resume, generally for i8xx class machines. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=16478 Reported-and-tested-by: Xavier Chantry Buzilla: https://bugs.freedesktop.org/show_bug.cgi?id=29413 Tested-by: Daniel Vetter Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ac38e4605ed2..d1c12435af48 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2376,11 +2376,19 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = crtc->dev; + if (HAS_PCH_SPLIT(dev)) { /* FDI link clock is fixed at 2.7G */ if (mode->clock * 3 > 27000 * 4) return MODE_CLOCK_HIGH; } + + /* XXX some encoders set the crtcinfo, others don't. + * Obviously we need some form of conflict resolution here... + */ + if (adjusted_mode->crtc_htotal == 0) + drm_mode_set_crtcinfo(adjusted_mode, 0); + return true; } -- cgit v1.2.3 From 97fe34b1a65bcdf9eb994423e95d7edb1ec491c5 Mon Sep 17 00:00:00 2001 From: Michael Cree Date: Wed, 1 Sep 2010 11:25:17 -0400 Subject: alpha: Fix printk format errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 3e073367a57d41e506f20aebb98e308387ce3090 upstream. When compiling alpha generic build get errors such as: arch/alpha/kernel/err_marvel.c: In function ‘marvel_print_err_cyc’: arch/alpha/kernel/err_marvel.c:119: error: format ‘%ld’ expects type ‘long int’, but argument 6 has type ‘u64’ Replaced a number of %ld format specifiers with %lld since u64 is unsigned long long. Signed-off-by: Michael Cree Signed-off-by: Matt Turner Signed-off-by: Greg Kroah-Hartman --- arch/alpha/kernel/err_marvel.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/alpha/kernel/err_marvel.c b/arch/alpha/kernel/err_marvel.c index 52a79dfc13c6..5c905aaaeccd 100644 --- a/arch/alpha/kernel/err_marvel.c +++ b/arch/alpha/kernel/err_marvel.c @@ -109,7 +109,7 @@ marvel_print_err_cyc(u64 err_cyc) #define IO7__ERR_CYC__CYCLE__M (0x7) printk("%s Packet In Error: %s\n" - "%s Error in %s, cycle %ld%s%s\n", + "%s Error in %s, cycle %lld%s%s\n", err_print_prefix, packet_desc[EXTRACT(err_cyc, IO7__ERR_CYC__PACKET)], err_print_prefix, @@ -313,7 +313,7 @@ marvel_print_po7_ugbge_sym(u64 ugbge_sym) } printk("%s Up Hose Garbage Symptom:\n" - "%s Source Port: %ld - Dest PID: %ld - OpCode: %s\n", + "%s Source Port: %lld - Dest PID: %lld - OpCode: %s\n", err_print_prefix, err_print_prefix, EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_SRC_PORT), @@ -552,7 +552,7 @@ marvel_print_pox_spl_cmplt(u64 spl_cmplt) #define IO7__POX_SPLCMPLT__REM_BYTE_COUNT__M (0xfff) printk("%s Split Completion Error:\n" - "%s Source (Bus:Dev:Func): %ld:%ld:%ld\n", + "%s Source (Bus:Dev:Func): %lld:%lld:%lld\n", err_print_prefix, err_print_prefix, EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__SOURCE_BUS), -- cgit v1.2.3 From 7273c1c64b2d4cb0ddfa7682ec7ab71dfe906398 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 26 Sep 2010 17:19:16 -0700 Subject: Linux 2.6.35.6 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 11aaa51e2298..78f927176f7f 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 35 -EXTRAVERSION = .5 +EXTRAVERSION = .6 NAME = Sheep on Meth # *DOCUMENTATION* -- cgit v1.2.3 From b0dd220aefe1ab80823cf13e9588c64fec151488 Mon Sep 17 00:00:00 2001 From: James Dingwall Date: Mon, 27 Sep 2010 09:37:17 +0100 Subject: Xen: fix typo in previous patch Correctly name the irq_chip structure to fix an immediate failure when booting as a xen pv_ops guest with a NULL pointer exception. The missing 'x' was introduced in commit [fb412a178502dc498430723b082a932f797e4763] applied to 2.6.3[25]-stable trees. The commit to mainline was [aaca49642b92c8a57d3ca5029a5a94019c7af69f] which did not have the problem. Signed-off-by: James Dingwall Reported-by: Pawel Zuzelski Tested-by: Pawel Zuzelski Signed-off-by: Greg Kroah-Hartman --- drivers/xen/events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 14ed3582025a..6830a4d067fc 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -935,7 +935,7 @@ static struct irq_chip xen_dynamic_chip __read_mostly = { .retrigger = retrigger_dynirq, }; -static struct irq_chip en_percpu_chip __read_mostly = { +static struct irq_chip xen_percpu_chip __read_mostly = { .name = "xen-percpu", .disable = disable_dynirq, -- cgit v1.2.3 From ea8a52f9f4bcc3420c38ae07f8378a2f18443970 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Sep 2010 18:09:08 -0700 Subject: Linux 2.6.35.7 Done at LinuxCon Tokyo 2010 --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 78f927176f7f..4c397f4168da 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 35 -EXTRAVERSION = .6 -NAME = Sheep on Meth +EXTRAVERSION = .7 +NAME = Yokohama # *DOCUMENTATION* # To see a list of typical targets execute "make help" -- cgit v1.2.3 From 9f09ac68e7af2001a24242cbe0f6e40e89dd6c62 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 28 Sep 2010 15:35:01 -0700 Subject: x86, cpu: After uncapping CPUID, re-run CPU feature detection commit d900329e20f4476db6461752accebcf7935a8055 upstream. After uncapping the CPUID level, we need to also re-run the CPU feature detection code. This resolves kernel bugzilla 16322. Reported-by: boris64 LKML-Reference: Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/common.c | 2 +- arch/x86/kernel/cpu/cpu.h | 1 + arch/x86/kernel/cpu/intel.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 68e4a6f2211e..296170084c80 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -537,7 +537,7 @@ void __cpuinit cpu_detect(struct cpuinfo_x86 *c) } } -static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) +void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) { u32 tfms, xlvl; u32 ebx; diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h index 3624e8a0f71b..f668bb1f7d43 100644 --- a/arch/x86/kernel/cpu/cpu.h +++ b/arch/x86/kernel/cpu/cpu.h @@ -33,5 +33,6 @@ extern const struct cpu_dev *const __x86_cpu_dev_start[], *const __x86_cpu_dev_end[]; extern void cpu_detect_cache_sizes(struct cpuinfo_x86 *c); +extern void get_cpu_cap(struct cpuinfo_x86 *c); #endif diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 85f69cdeae10..b4389441efbb 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -39,6 +39,7 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) misc_enable &= ~MSR_IA32_MISC_ENABLE_LIMIT_CPUID; wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable); c->cpuid_level = cpuid_eax(0); + get_cpu_cap(c); } } -- cgit v1.2.3 From 292a45371086815942ec1ebb4e369aeee9355db0 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Sat, 25 Sep 2010 11:07:27 -0400 Subject: ALSA: sound/pci/rme9652: prevent reading uninitialized stack memory commit e68d3b316ab7b02a074edc4f770e6a746390cb7d upstream. The SNDRV_HDSP_IOCTL_GET_CONFIG_INFO and SNDRV_HDSP_IOCTL_GET_CONFIG_INFO ioctls in hdspm.c and hdsp.c allow unprivileged users to read uninitialized kernel stack memory, because several fields of the hdsp{m}_config_info structs declared on the stack are not altered or zeroed before being copied back to the user. This patch takes care of it. Signed-off-by: Dan Rosenberg Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/rme9652/hdsp.c | 1 + sound/pci/rme9652/hdspm.c | 1 + 2 files changed, 2 insertions(+) diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index b92adef8e81e..d6fa7bfd9aa1 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -4609,6 +4609,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne if (err < 0) return err; + memset(&info, 0, sizeof(info)); spin_lock_irqsave(&hdsp->lock, flags); info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp); info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp); diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 547b713d7204..0c98ef9156d8 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -4127,6 +4127,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO: + memset(&info, 0, sizeof(info)); spin_lock_irq(&hdspm->lock); info.pref_sync_ref = hdspm_pref_sync_ref(hdspm); info.wordclock_sync_check = hdspm_wc_sync_check(hdspm); -- cgit v1.2.3 From a09d28ae69b42f3b6093b8e76f47400d94c8bfda Mon Sep 17 00:00:00 2001 From: "Erik J. Staab" Date: Wed, 22 Sep 2010 11:07:41 +0200 Subject: ALSA: oxygen: fix analog capture on Claro halo cards commit 0873a5ae747847ee55a63db409dff3476e45bcd9 upstream. On the HT-Omega Claro halo card, the ADC data must be captured from the second I2S input. Using the default first input, which isn't connected to anything, would result in silence. Signed-off-by: Erik J. Staab Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/oxygen/oxygen.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index 289cb4dacfc7..6c0a11adb2a8 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c @@ -543,6 +543,10 @@ static int __devinit get_oxygen_model(struct oxygen *chip, chip->model.suspend = claro_suspend; chip->model.resume = claro_resume; chip->model.set_adc_params = set_ak5385_params; + chip->model.device_config = PLAYBACK_0_TO_I2S | + PLAYBACK_1_TO_SPDIF | + CAPTURE_0_FROM_I2S_2 | + CAPTURE_1_FROM_SPDIF; break; } if (id->driver_data == MODEL_MERIDIAN || -- cgit v1.2.3 From e5d843fbf633dc65353bc08ee28f6b08ce651a4d Mon Sep 17 00:00:00 2001 From: Luke Yelavich Date: Tue, 21 Sep 2010 17:05:46 +1000 Subject: ALSA: hda - Add Dell Latitude E6400 model quirk commit 0f9f1ee9d1412d45a22bfd69dfd4d4324b506e9e upstream. BugLink: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/643891 Set the Dell Latitude E6400 (1028:0233) SSID to use AD1984_DELL_DESKTOP Signed-off-by: Luke Yelavich Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_analog.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index afbe314a5bf3..6258a053b20c 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -3641,6 +3641,7 @@ static struct snd_pci_quirk ad1984_cfg_tbl[] = { /* Lenovo Thinkpad T61/X61 */ SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD), SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP), + SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP), {} }; -- cgit v1.2.3 From b81cb9277507012a8d44e6b4efbbaba4fce19299 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Tue, 28 Sep 2010 14:18:20 -0400 Subject: ALSA: prevent heap corruption in snd_ctl_new() commit 5591bf07225523600450edd9e6ad258bb877b779 upstream. The snd_ctl_new() function in sound/core/control.c allocates space for a snd_kcontrol struct by performing arithmetic operations on a user-provided size without checking for integer overflow. If a user provides a large enough size, an overflow will occur, the allocated chunk will be too small, and a second user-influenced value will be written repeatedly past the bounds of this chunk. This code is reachable by unprivileged users who have permission to open a /dev/snd/controlC* device (on many distros, this is group "audio") via the SNDRV_CTL_IOCTL_ELEM_ADD and SNDRV_CTL_IOCTL_ELEM_REPLACE ioctls. Signed-off-by: Dan Rosenberg Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/core/control.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/core/control.c b/sound/core/control.c index 070aab490191..45a818002d99 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -31,6 +31,7 @@ /* max number of user-defined controls */ #define MAX_USER_CONTROLS 32 +#define MAX_CONTROL_COUNT 1028 struct snd_kctl_ioctl { struct list_head list; /* list of all ioctls */ @@ -195,6 +196,10 @@ static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control, if (snd_BUG_ON(!control || !control->count)) return NULL; + + if (control->count > MAX_CONTROL_COUNT) + return NULL; + kctl = kzalloc(sizeof(*kctl) + sizeof(struct snd_kcontrol_volatile) * control->count, GFP_KERNEL); if (kctl == NULL) { snd_printk(KERN_ERR "Cannot allocate control instance\n"); -- cgit v1.2.3 From 105f55f7a395070e6369383ce25721de353a18c3 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Fri, 15 Oct 2010 12:06:18 +0200 Subject: ALSA: rawmidi: fix oops (use after free) when unloading a driver module commit aa73aec6c385e2c797ac25cc7ccf0318031de7c8 upstream. When a driver module is unloaded and the last still open file is a raw MIDI device, the card and its devices will be actually freed in the snd_card_file_remove() call when that file is closed. Afterwards, rmidi and rmidi->card point into freed memory, so the module pointer is likely to be garbage. (This was introduced by commit 9a1b64caac82aa02cb74587ffc798e6f42c6170a.) Signed-off-by: Clemens Ladisch Reported-by: Krzysztof Foltman Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/core/rawmidi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index eb68326c37d4..75490c6ed7e3 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -535,13 +535,15 @@ static int snd_rawmidi_release(struct inode *inode, struct file *file) { struct snd_rawmidi_file *rfile; struct snd_rawmidi *rmidi; + struct module *module; rfile = file->private_data; rmidi = rfile->rmidi; rawmidi_release_priv(rfile); kfree(rfile); + module = rmidi->card->module; snd_card_file_remove(rmidi->card, file); - module_put(rmidi->card->module); + module_put(module); return 0; } -- cgit v1.2.3 From 085835efc676aa2a52395252b17bb91716a61925 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 23 Sep 2010 10:01:11 -0700 Subject: hwmon: (lis3) Fix Oops with NULL platform data commit f7c77a3dc4683659b6f0d1b6cbc82b6253d095e0 upstream. The recent addition of threaded irq handler causes a NULL dereference when used with hp_accel driver, which has NULL pdata. Acked-by: Samu Onkalo Signed-off-by: Takashi Iwai Signed-off-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/lis3lv02d.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c index 6138f036b159..fc591ae53107 100644 --- a/drivers/hwmon/lis3lv02d.c +++ b/drivers/hwmon/lis3lv02d.c @@ -277,7 +277,7 @@ static irqreturn_t lis302dl_interrupt(int irq, void *dummy) wake_up_interruptible(&lis3_dev.misc_wait); kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN); out: - if (lis3_dev.whoami == WAI_8B && lis3_dev.idev && + if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev && lis3_dev.idev->input->users) return IRQ_WAKE_THREAD; return IRQ_HANDLED; @@ -718,7 +718,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) * io-apic is not configurable (and generates a warning) but I keep it * in case of support for other hardware. */ - if (dev->whoami == WAI_8B) + if (dev->pdata && dev->whoami == WAI_8B) thread_fn = lis302dl_interrupt_thread1_8b; else thread_fn = NULL; -- cgit v1.2.3 From 366caa1da0d299aa7ec33bbb131bb00aebadb993 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 21 Sep 2010 15:01:53 -0400 Subject: USB: fix bug in initialization of interface minor numbers commit 0026e00523a85b90a92a93ddf6660939ecef3e54 upstream. Recent changes in the usbhid layer exposed a bug in usbcore. If CONFIG_USB_DYNAMIC_MINORS is enabled then an interface may be assigned a minor number of 0. However interfaces that aren't registered as USB class devices also have their minor number set to 0, during initialization. As a result usb_find_interface() may return the wrong interface, leading to a crash. This patch (as1418) fixes the problem by initializing every interface's minor number to -1. It also cleans up the usb_register_dev() function, which besides being somewhat awkwardly written, does not unwind completely on all its error paths. Signed-off-by: Alan Stern Tested-by: Philip J. Turmel Tested-by: Gabriel Craciunescu Tested-by: Alex Riesen Tested-by: Matthias Bayer CC: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/file.c | 35 ++++++++++++++++------------------- drivers/usb/core/message.c | 1 + 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index f06f5dbc8cdc..1e6ccef2cf0c 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -159,9 +159,9 @@ void usb_major_cleanup(void) int usb_register_dev(struct usb_interface *intf, struct usb_class_driver *class_driver) { - int retval = -EINVAL; + int retval; int minor_base = class_driver->minor_base; - int minor = 0; + int minor; char name[20]; char *temp; @@ -173,12 +173,17 @@ int usb_register_dev(struct usb_interface *intf, */ minor_base = 0; #endif - intf->minor = -1; - - dbg ("looking for a minor, starting at %d", minor_base); if (class_driver->fops == NULL) - goto exit; + return -EINVAL; + if (intf->minor >= 0) + return -EADDRINUSE; + + retval = init_usb_class(); + if (retval) + return retval; + + dev_dbg(&intf->dev, "looking for a minor, starting at %d", minor_base); down_write(&minor_rwsem); for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) { @@ -186,20 +191,12 @@ int usb_register_dev(struct usb_interface *intf, continue; usb_minors[minor] = class_driver->fops; - - retval = 0; + intf->minor = minor; break; } up_write(&minor_rwsem); - - if (retval) - goto exit; - - retval = init_usb_class(); - if (retval) - goto exit; - - intf->minor = minor; + if (intf->minor < 0) + return -EXFULL; /* create a usb class device for this usb interface */ snprintf(name, sizeof(name), class_driver->name, minor - minor_base); @@ -213,11 +210,11 @@ int usb_register_dev(struct usb_interface *intf, "%s", temp); if (IS_ERR(intf->usb_dev)) { down_write(&minor_rwsem); - usb_minors[intf->minor] = NULL; + usb_minors[minor] = NULL; + intf->minor = -1; up_write(&minor_rwsem); retval = PTR_ERR(intf->usb_dev); } -exit: return retval; } EXPORT_SYMBOL_GPL(usb_register_dev); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 844683e50383..9f0ce7de0e36 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1802,6 +1802,7 @@ free_interfaces: intf->dev.groups = usb_interface_groups; intf->dev.dma_mask = dev->dev.dma_mask; INIT_WORK(&intf->reset_ws, __usb_queue_reset_device); + intf->minor = -1; device_initialize(&intf->dev); dev_set_name(&intf->dev, "%d-%s:%d.%d", dev->bus->busnum, dev->devpath, -- cgit v1.2.3 From c9c7a50d0b30c460697328552e729e9bdc7f1908 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Mon, 20 Sep 2010 10:32:01 +0300 Subject: usb: musb: gadget: fix kernel panic if using out ep with FIFO_TXRX style commit bd2e74d657fc7d514881cc2117e323790b257914 upstream. For shared fifo hw endpoint(with FIFO_TXRX style), only ep_in field of musb_hw_ep is intialized in musb_g_init_endpoints, and ep_out is not initialized, but musb_g_rx and rxstate may access ep_out field of musb_hw_ep by the method below: musb_ep = &musb->endpoints[epnum].ep_out which can cause the kernel panic[1] below, this patch fixes the issue by getting 'musb_ep' from '&musb->endpoints[epnum].ep_in' for shared fifo endpoint. [1], kernel panic [root@OMAP3EVM /]# musb_interrupt 1583: ** IRQ peripheral usb0008 tx0000 rx4000 musb_stage0_irq 460: <== Power=f0, DevCtl=99, int_usb=0x8 musb_g_rx 772: <== (null), rxcsr 4007 ffffffe8 musb_g_rx 786: iso overrun on ffffffe8 Unable to handle kernel NULL pointer dereference at virtual address 00000008 pgd = c0004000 [00000008] *pgd=00000000 Internal error: Oops: 17 [#1] PREEMPT last sysfs file: /sys/devices/platform/musb_hdrc/usb1/usb_device/usbdev1.1/dev Modules linked in: g_zero CPU: 0 Tainted: G W (2.6.35-rc6-gkh-wl+ #92) PC is at musb_g_rx+0xfc/0x2ec LR is at vprintk+0x3f4/0x458 pc : [] lr : [] psr: 20000193 sp : c760bd78 ip : c03c9d70 fp : c760bdbc r10: 00000000 r9 : fa0ab1e0 r8 : 0000000e r7 : c7e80158 r6 : ffffffe8 r5 : 00000001 r4 : 00004003 r3 : 00010003 r2 : c760bcd8 r1 : c03cd030 r0 : 0000002e Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernel Control: 10c5387d Table: 8778c019 DAC: 00000017 Process kmemleak (pid: 421, stack limit = 0xc760a2e8) Stack: (0xc760bd78 to 0xc760c000) bd60: ffffffe8 c04b1b58 bd80: ffffffe8 c7c01ac0 00000000 c7e80d24 c0084238 00000001 00000001 c7e80158 bda0: 0000000e 00000008 00000099 000000f0 c760be04 c760bdc0 c02bcd68 c02c06b4 bdc0: 00000099 00000008 00004000 c760bdd8 c03cc4f8 00000000 00000002 c7e80158 bde0: c7d2e300 60000193 c760a000 0000005c 00000000 00000000 c760be24 c760be08 be00: c02bcecc c02bc1ac c7d2e300 c7d2e300 0000005c c760a000 c760be54 c760be28 be20: c00ad698 c02bce6c 00000000 c7d2e300 c067c258 0000005c c067c294 00000001 be40: c760a000 00000000 c760be74 c760be58 c00af984 c00ad5fc 0000005c 00000000 be60: 00000000 00000002 c760be8c c760be78 c0039080 c00af8d0 ffffffff fa200000 be80: c760beec c760be90 c0039b6c c003900c 00000001 00000000 c7d1e240 00000000 bea0: 00000000 c068bae8 00000000 60000013 00000001 00000000 00000000 c760beec bec0: c0064ecc c760bed8 c00ff7d0 c003a0a8 60000013 ffffffff 00000000 c068bae8 bee0: c760bf24 c760bef0 c00ff7d0 c0064ec4 00000001 00000000 c00ff700 00000000 bf00: c0087f00 00000000 60000013 c0d76a70 c0e23795 00000001 c760bf4c c760bf28 bf20: c00ffdd8 c00ff70c c068bb08 c068bae8 60000013 c0100938 c068bb30 00000000 bf40: c760bf84 c760bf50 c010014c c00ffd84 00000001 00000000 c010000c 00012c00 bf60: c7c33f04 00012c00 c7c33f04 00000000 c0100938 00000000 c760bf9c c760bf88 bf80: c01009a8 c0100018 c760bfa8 c7c33f04 c760bff4 c760bfa0 c0088000 c0100944 bfa0: c760bf98 00000000 00000000 00000001 dead4ead ffffffff ffffffff c08ba2bc bfc0: 00000000 c049e7fa 00000000 c0087f70 c760bfd0 c760bfd0 c7c33f04 c0087f70 bfe0: c006f5e8 00000013 00000000 c760bff8 c006f5e8 c0087f7c 7f0004ff df2000ff Backtrace: [] (musb_g_rx+0x0/0x2ec) from [] (musb_interrupt+0xbc8/0xcc0) [] (musb_interrupt+0x0/0xcc0) from [] (generic_interrupt+0x6c/0x84) [] (generic_interrupt+0x0/0x84) from [] (handle_IRQ_event+0xa8/0x1ec) r7:c760a000 r6:0000005c r5:c7d2e300 r4:c7d2e300 [] (handle_IRQ_event+0x0/0x1ec) from [] (handle_level_irq+0xc0/0x13c) [] (handle_level_irq+0x0/0x13c) from [] (asm_do_IRQ+0x80/0xa0) r7:00000002 r6:00000000 r5:00000000 r4:0000005c [] (asm_do_IRQ+0x0/0xa0) from [] (__irq_svc+0x4c/0xb4) Exception stack(0xc760be90 to 0xc760bed8) be80: 00000001 00000000 c7d1e240 00000000 bea0: 00000000 c068bae8 00000000 60000013 00000001 00000000 00000000 c760beec bec0: c0064ecc c760bed8 c00ff7d0 c003a0a8 60000013 ffffffff r5:fa200000 r4:ffffffff [] (sub_preempt_count+0x0/0x100) from [] (find_and_get_object+0xd0/0x110) r5:c068bae8 r4:00000000 [] (find_and_get_object+0x0/0x110) from [] (scan_block+0x60/0x104) r8:00000001 r7:c0e23795 r6:c0d76a70 r5:60000013 r4:00000000 [] (scan_block+0x0/0x104) from [] (kmemleak_scan+0x140/0x484) [] (kmemleak_scan+0x0/0x484) from [] (kmemleak_scan_thread+0x70/0xcc) r8:00000000 r7:c0100938 r6:00000000 r5:c7c33f04 r4:00012c00 [] (kmemleak_scan_thread+0x0/0xcc) from [] (kthread+0x90/0x98) r5:c7c33f04 r4:c760bfa8 [] (kthread+0x0/0x98) from [] (do_exit+0x0/0x684) r7:00000013 r6:c006f5e8 r5:c0087f70 r4:c7c33f04 Code: e3002312 e58d6000 e2833e16 eb0422d5 (e5963020) ---[ end trace f3d5e96f75c297b7 ]--- Signed-off-by: Ming Lei Reviewed-by: Sergei Shtylyov Cc: David Brownell Cc: Anand Gadiyar Cc: Mike Frysinger Cc: Sergei Shtylyov Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 6fca870e957e..de0ca90ceb9b 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -568,11 +568,19 @@ static void rxstate(struct musb *musb, struct musb_request *req) { const u8 epnum = req->epnum; struct usb_request *request = &req->request; - struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out; + struct musb_ep *musb_ep; void __iomem *epio = musb->endpoints[epnum].regs; unsigned fifo_count = 0; - u16 len = musb_ep->packet_sz; + u16 len; u16 csr = musb_readw(epio, MUSB_RXCSR); + struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; + + if (hw_ep->is_shared_fifo) + musb_ep = &hw_ep->ep_in; + else + musb_ep = &hw_ep->ep_out; + + len = musb_ep->packet_sz; /* We shouldn't get here while DMA is active, but we do... */ if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) { @@ -740,9 +748,15 @@ void musb_g_rx(struct musb *musb, u8 epnum) u16 csr; struct usb_request *request; void __iomem *mbase = musb->mregs; - struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out; + struct musb_ep *musb_ep; void __iomem *epio = musb->endpoints[epnum].regs; struct dma_channel *dma; + struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; + + if (hw_ep->is_shared_fifo) + musb_ep = &hw_ep->ep_in; + else + musb_ep = &hw_ep->ep_out; musb_ep_select(mbase, epnum); -- cgit v1.2.3 From 6ce3cb681079d1f8274608b05d95b665fe66ed49 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 11 Sep 2010 13:23:12 -0500 Subject: usb: musb: gadget: restart request on clearing endpoint halt commit a666e3e6098a9f56310e4ec2705f1dad124a34b5 upstream. Commit 46034dca515bc4ddca0399ae58106d1f5f0d809f (USB: musb_gadget_ep0: stop abusing musb_gadget_set_halt()) forgot to restart a queued request after clearing the endpoint halt feature. This results in a couple of USB resets while enumerating the file-backed storage gadget due to CSW packet not being sent for the MODE SENSE(10) command. Signed-off-by: Sergei Shtylyov Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget.c | 2 +- drivers/usb/musb/musb_gadget.h | 2 ++ drivers/usb/musb/musb_gadget_ep0.c | 9 +++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index de0ca90ceb9b..180da4e35ac0 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1095,7 +1095,7 @@ struct free_record { /* * Context: controller locked, IRQs blocked. */ -static void musb_ep_restart(struct musb *musb, struct musb_request *req) +void musb_ep_restart(struct musb *musb, struct musb_request *req) { DBG(3, "<== %s request %p len %u on hw_ep%d\n", req->tx ? "TX/IN" : "RX/OUT", diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h index c8b140325d82..572b1da7f2dc 100644 --- a/drivers/usb/musb/musb_gadget.h +++ b/drivers/usb/musb/musb_gadget.h @@ -105,4 +105,6 @@ extern void musb_gadget_cleanup(struct musb *); extern void musb_g_giveback(struct musb_ep *, struct usb_request *, int); +extern void musb_ep_restart(struct musb *, struct musb_request *); + #endif /* __MUSB_GADGET_H */ diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index 21b9788d0243..ecae71430098 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -261,6 +261,7 @@ __acquires(musb->lock) ctrlrequest->wIndex & 0x0f; struct musb_ep *musb_ep; struct musb_hw_ep *ep; + struct musb_request *request; void __iomem *regs; int is_in; u16 csr; @@ -302,6 +303,14 @@ __acquires(musb->lock) musb_writew(regs, MUSB_RXCSR, csr); } + /* Maybe start the first request in the queue */ + request = to_musb_request( + next_request(musb_ep)); + if (!musb_ep->busy && request) { + DBG(3, "restarting the request\n"); + musb_ep_restart(musb, request); + } + /* select ep0 again */ musb_ep_select(mbase, 0); } break; -- cgit v1.2.3 From dc7237c6b7b529c5da2776cbb8b68cc74d1555c3 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Tue, 5 Oct 2010 17:20:16 +0200 Subject: HID: hidraw, fix a NULL pointer dereference in hidraw_ioctl commit d20d5ffab92f00188f360c44c791a5ffb988247c upstream. BUG: unable to handle kernel NULL pointer dereference at 0000000000000028 IP: [] hidraw_ioctl+0xfc/0x32c [hid] [...] This is reproducible by disconnecting the device while userspace does ioctl in a loop and doesn't check return values in order to exit the loop. Signed-off-by: Antonio Ospite Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hidraw.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 3ccd47850677..f43e95e11d48 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -246,6 +246,10 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, mutex_lock(&minors_lock); dev = hidraw_table[minor]; + if (!dev) { + ret = -ENODEV; + goto out; + } switch (cmd) { case HIDIOCGRDESCSIZE: @@ -319,6 +323,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, ret = -ENOTTY; } +out: mutex_unlock(&minors_lock); return ret; } -- cgit v1.2.3 From cdcaefbcdc06c945dec978a9015f25f86e622844 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Tue, 5 Oct 2010 17:20:17 +0200 Subject: HID: hidraw, fix a NULL pointer dereference in hidraw_write commit e42dee9a99a3ecd32b5c027e8f7411fb5bc11eb6 upstream. BUG: unable to handle kernel NULL pointer dereference at 0000000000000028 IP: [] hidraw_write+0x3b/0x116 [hid] [...] This is reproducible by disconnecting the device while userspace writes to dev node in a loop and doesn't check return values in order to exit the loop. Signed-off-by: Antonio Ospite Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hidraw.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index f43e95e11d48..7dca2faacdfa 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -111,6 +111,12 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t int ret = 0; mutex_lock(&minors_lock); + + if (!hidraw_table[minor]) { + ret = -ENODEV; + goto out; + } + dev = hidraw_table[minor]->hid; if (!dev->hid_output_raw_report) { -- cgit v1.2.3 From 51793adc68ef938da175436919ab0db1c379eb18 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 21 Sep 2010 09:25:48 +0200 Subject: ahci: fix module refcount breakage introduced by libahci split commit fad16e7a7f67eef8d33f8ad58850db89382b09ce upstream. libata depends on scsi_host_template for module reference counting and sht's should be owned by each low level driver. During libahci split, the sht was left with libahci.ko leaving the actual low level drivers not reference counted. This made ahci and ahci_platform always unloadable even while they're being actively used. Fix it by defining AHCI_SHT() macro in ahci.h and defining a sht for each low level ahci driver. stable: only applicable to 2.6.35. Signed-off-by: Tejun Heo Reported-by: Pedro Francisco Tested-by: Michael Tokarev Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/ahci.c | 4 ++++ drivers/ata/ahci.h | 12 +++++++++++- drivers/ata/ahci_platform.c | 6 +++++- drivers/ata/libahci.c | 16 ++++------------ 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index f2522534ae63..d571e3f24b32 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -89,6 +89,10 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); static int ahci_pci_device_resume(struct pci_dev *pdev); #endif +static struct scsi_host_template ahci_sht = { + AHCI_SHT("ahci"), +}; + static struct ata_port_operations ahci_vt8251_ops = { .inherits = &ahci_ops, .hardreset = ahci_vt8251_hardreset, diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 7113c5724471..88aa888a7e14 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -297,7 +297,17 @@ struct ahci_host_priv { extern int ahci_ignore_sss; -extern struct scsi_host_template ahci_sht; +extern struct device_attribute *ahci_shost_attrs[]; +extern struct device_attribute *ahci_sdev_attrs[]; + +#define AHCI_SHT(drv_name) \ + ATA_NCQ_SHT(drv_name), \ + .can_queue = AHCI_MAX_CMDS - 1, \ + .sg_tablesize = AHCI_MAX_SG, \ + .dma_boundary = AHCI_DMA_BOUNDARY, \ + .shost_attrs = ahci_shost_attrs, \ + .sdev_attrs = ahci_sdev_attrs + extern struct ata_port_operations ahci_ops; void ahci_save_initial_config(struct device *dev, diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 5e11b160f247..9366743e37f4 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -23,6 +23,10 @@ #include #include "ahci.h" +static struct scsi_host_template ahci_platform_sht = { + AHCI_SHT("ahci_platform"), +}; + static int __init ahci_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -140,7 +144,7 @@ static int __init ahci_probe(struct platform_device *pdev) ahci_print_info(host, "platform"); rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, - &ahci_sht); + &ahci_platform_sht); if (rc) goto err0; diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 98c80e1ab6e9..b765a01cd272 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -121,7 +121,7 @@ static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL); static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO, ahci_read_em_buffer, ahci_store_em_buffer); -static struct device_attribute *ahci_shost_attrs[] = { +struct device_attribute *ahci_shost_attrs[] = { &dev_attr_link_power_management_policy, &dev_attr_em_message_type, &dev_attr_em_message, @@ -132,22 +132,14 @@ static struct device_attribute *ahci_shost_attrs[] = { &dev_attr_em_buffer, NULL }; +EXPORT_SYMBOL_GPL(ahci_shost_attrs); -static struct device_attribute *ahci_sdev_attrs[] = { +struct device_attribute *ahci_sdev_attrs[] = { &dev_attr_sw_activity, &dev_attr_unload_heads, NULL }; - -struct scsi_host_template ahci_sht = { - ATA_NCQ_SHT("ahci"), - .can_queue = AHCI_MAX_CMDS - 1, - .sg_tablesize = AHCI_MAX_SG, - .dma_boundary = AHCI_DMA_BOUNDARY, - .shost_attrs = ahci_shost_attrs, - .sdev_attrs = ahci_sdev_attrs, -}; -EXPORT_SYMBOL_GPL(ahci_sht); +EXPORT_SYMBOL_GPL(ahci_sdev_attrs); struct ata_port_operations ahci_ops = { .inherits = &sata_pmp_port_ops, -- cgit v1.2.3 From a7b048db83992dba877da7b85d8b1236324f9763 Mon Sep 17 00:00:00 2001 From: Don Mullis Date: Thu, 30 Sep 2010 15:15:32 -0700 Subject: lib/list_sort: do not pass bad pointers to cmp callback commit f015ac3edd84ad72f88e08a4d83c56c360aae404 upstream. If the original list is a POT in length, the first callback from line 73 will pass a==b both pointing to the original list_head. This is dangerous because the 'list_sort()' user can use 'container_of()' and accesses the "containing" object, which does not necessary exist for the list head. So the user can access RAM which does not belong to him. If this is a write access, we can end up with memory corruption. Signed-off-by: Don Mullis Tested-by: Artem Bityutskiy Signed-off-by: Artem Bityutskiy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- lib/list_sort.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/list_sort.c b/lib/list_sort.c index 4b5cb794c38b..a7616fa3162e 100644 --- a/lib/list_sort.c +++ b/lib/list_sort.c @@ -70,7 +70,7 @@ static void merge_and_restore_back_links(void *priv, * element comparison is needed, so the client's cmp() * routine can invoke cond_resched() periodically. */ - (*cmp)(priv, tail, tail); + (*cmp)(priv, tail->next, tail->next); tail->next->prev = tail; tail = tail->next; -- cgit v1.2.3 From cc64346cc6b102a93ae8f2cc021de152d122fd43 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 28 Sep 2010 22:57:02 -0400 Subject: ACPI: invoke DSDT corruption workaround on all Toshiba Satellite commit 100cf87788c0e9104f6fb1b0ff5f72f73fbbbea3 upstream. Our list of Toshiba Satellite models that require this workaround is growing -- so invoke the workaround for the entire product line. https://bugzilla.kernel.org/show_bug.cgi?id=14679 Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/bus.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index c1d23cd71652..a33fbc9d1dce 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -80,23 +80,15 @@ static int set_copy_dsdt(const struct dmi_system_id *id) static struct dmi_system_id dsdt_dmi_table[] __initdata = { /* - * Insyde BIOS on some TOSHIBA machines corrupt the DSDT. + * Invoke DSDT corruption work-around on all Toshiba Satellite. * https://bugzilla.kernel.org/show_bug.cgi?id=14679 */ { .callback = set_copy_dsdt, - .ident = "TOSHIBA Satellite A505", + .ident = "TOSHIBA Satellite", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A505"), - }, - }, - { - .callback = set_copy_dsdt, - .ident = "TOSHIBA Satellite L505D", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L505D"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"), }, }, {} -- cgit v1.2.3 From b3d8659df019031a5829528b991e1e90d6139207 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 21 Sep 2010 03:26:35 -0400 Subject: oprofile: Add Support for Intel CPU Family 6 / Model 29 commit bb7ab785ad05a97a2c9ffb3a06547ed39f3133e8 upstream. This patch adds CPU type detection for dunnington processor (Family 6 / Model 29) to be identified as core 2 family cpu type (wikipedia source). I tested oprofile on Intel(R) Xeon(R) CPU E7440 reporting itself as model 29, and it runs without an issue. Spec: http://www.intel.com/Assets/en_US/PDF/specupdate/320336.pdf Signed-off-by: Jiri Olsa Acked-by: Andi Kleen Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman --- arch/x86/oprofile/nmi_int.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 009b819f48d0..f1575c9a2572 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -674,6 +674,7 @@ static int __init ppro_init(char **cpu_type) case 0x0f: case 0x16: case 0x17: + case 0x1d: *cpu_type = "i386/core_2"; break; case 0x1a: -- cgit v1.2.3 From 1b6740a13ca9774810edacafc5e12514092651e2 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 29 Sep 2010 16:52:25 +0200 Subject: oprofile, ARM: Release resources on failure commit 98d943b02f6f1b57787ff1aa6f34d019a407e3ee upstream. This patch fixes a resource leak on failure, where the oprofilefs and some counters may not released properly. Signed-off-by: Robert Richter Acked-by: Will Deacon Cc: linux-arm-kernel@lists.infradead.org LKML-Reference: <20100929145225.GJ13563@erda.amd.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/arm/oprofile/common.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c index 0691176899ff..72e09eb642dd 100644 --- a/arch/arm/oprofile/common.c +++ b/arch/arm/oprofile/common.c @@ -102,6 +102,7 @@ static int op_create_counter(int cpu, int event) if (IS_ERR(pevent)) { ret = PTR_ERR(pevent); } else if (pevent->state != PERF_EVENT_STATE_ACTIVE) { + perf_event_release_kernel(pevent); pr_warning("oprofile: failed to enable event %d " "on CPU %d\n", event, cpu); ret = -EBUSY; @@ -365,6 +366,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) ret = init_driverfs(); if (ret) { kfree(counter_config); + counter_config = NULL; return ret; } @@ -402,7 +404,6 @@ void oprofile_arch_exit(void) struct perf_event *event; if (*perf_events) { - exit_driverfs(); for_each_possible_cpu(cpu) { for (id = 0; id < perf_num_counters; ++id) { event = perf_events[cpu][id]; @@ -413,8 +414,10 @@ void oprofile_arch_exit(void) } } - if (counter_config) + if (counter_config) { kfree(counter_config); + exit_driverfs(); + } } #else int __init oprofile_arch_init(struct oprofile_operations *ops) -- cgit v1.2.3 From b8a7e2b687977fa0a2d0969d8e32fe6f5a4fbff4 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Sat, 18 Sep 2010 19:38:21 -0500 Subject: RDMA/cxgb3: Turn off RX coalescing for iWARP connections commit bec658ff31453a5726b1c188674d587a5d40c482 upstream. The HW by default has RX coalescing on. For iWARP connections, this causes a 100ms delay in connection establishement due to the ingress MPA Start message being stalled in HW. So explicitly turn RX coalescing off when setting up iWARP connections. This was causing very bad performance for NP64 gather operations using Open MPI, due to the way it sets up connections on larger jobs. Signed-off-by: Steve Wise Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/cxgb3/iwch_cm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index ebfb117ba68b..9c05ddd65a8f 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -463,7 +463,8 @@ static int send_connect(struct iwch_ep *ep) V_MSS_IDX(mtu_idx) | V_L2T_IDX(ep->l2t->idx) | V_TX_CHANNEL(ep->l2t->smt_idx); opt0l = V_TOS((ep->tos >> 2) & M_TOS) | V_RCV_BUFSIZ(rcv_win>>10); - opt2 = V_FLAVORS_VALID(1) | V_CONG_CONTROL_FLAVOR(cong_flavor); + opt2 = F_RX_COALESCE_VALID | V_RX_COALESCE(0) | V_FLAVORS_VALID(1) | + V_CONG_CONTROL_FLAVOR(cong_flavor); skb->priority = CPL_PRIORITY_SETUP; set_arp_failure_handler(skb, act_open_req_arp_failure); @@ -1280,7 +1281,8 @@ static void accept_cr(struct iwch_ep *ep, __be32 peer_ip, struct sk_buff *skb) V_MSS_IDX(mtu_idx) | V_L2T_IDX(ep->l2t->idx) | V_TX_CHANNEL(ep->l2t->smt_idx); opt0l = V_TOS((ep->tos >> 2) & M_TOS) | V_RCV_BUFSIZ(rcv_win>>10); - opt2 = V_FLAVORS_VALID(1) | V_CONG_CONTROL_FLAVOR(cong_flavor); + opt2 = F_RX_COALESCE_VALID | V_RX_COALESCE(0) | V_FLAVORS_VALID(1) | + V_CONG_CONTROL_FLAVOR(cong_flavor); rpl = cplhdr(skb); rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); -- cgit v1.2.3 From 786c022aa4e6ba6805f52a49b64d948caa8b9969 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 11 Oct 2010 12:41:32 -0400 Subject: drm/radeon/kms: fix bad cast/shift in evergreen.c commit d31dba58480c3cdd458f449261d72ecd15287792 upstream. Missing parens. fixes: https://bugs.freedesktop.org/show_bug.cgi?id=30718 Reported-by: Dave Gilbert Signed-off-by: Alex Deucher Reviewed-by: Matt Turner Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index d448c25d25c8..0bfb83638a5d 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1120,7 +1120,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev) WREG32(RCU_IND_INDEX, 0x203); efuse_straps_3 = RREG32(RCU_IND_DATA); - efuse_box_bit_127_124 = (u8)(efuse_straps_3 & 0xF0000000) >> 28; + efuse_box_bit_127_124 = (u8)((efuse_straps_3 & 0xF0000000) >> 28); switch(efuse_box_bit_127_124) { case 0x0: -- cgit v1.2.3 From 895384a47efb08e694fe5a72be140f463402544c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 14 Oct 2010 17:14:57 -0400 Subject: drm/radeon/kms: avivo cursor workaround applies to evergreen as well commit 6a2a11dbea5db417d200d38dda53c30a2e5603e0 upstream. Fixes cursor corruption in certain cases. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_cursor.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 4eb67c0e0996..f7ce8e130bb7 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -203,6 +203,7 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct radeon_device *rdev = crtc->dev->dev_private; int xorigin = 0, yorigin = 0; + int w = radeon_crtc->cursor_width; if (x < 0) xorigin = -x + 1; @@ -213,22 +214,7 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, if (yorigin >= CURSOR_HEIGHT) yorigin = CURSOR_HEIGHT - 1; - radeon_lock_cursor(crtc, true); - if (ASIC_IS_DCE4(rdev)) { - /* cursors are offset into the total surface */ - x += crtc->x; - y += crtc->y; - DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y); - - /* XXX: check if evergreen has the same issues as avivo chips */ - WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, - ((xorigin ? 0 : x) << 16) | - (yorigin ? 0 : y)); - WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); - WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset, - ((radeon_crtc->cursor_width - 1) << 16) | (radeon_crtc->cursor_height - 1)); - } else if (ASIC_IS_AVIVO(rdev)) { - int w = radeon_crtc->cursor_width; + if (ASIC_IS_AVIVO(rdev)) { int i = 0; struct drm_crtc *crtc_p; @@ -260,7 +246,17 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, if (w <= 0) w = 1; } + } + radeon_lock_cursor(crtc, true); + if (ASIC_IS_DCE4(rdev)) { + WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, + ((xorigin ? 0 : x) << 16) | + (yorigin ? 0 : y)); + WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); + WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset, + ((w - 1) << 16) | (radeon_crtc->cursor_height - 1)); + } else if (ASIC_IS_AVIVO(rdev)) { WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y)); -- cgit v1.2.3 From 134da12cdde543d62dfcb3a39f6487edee674339 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Sat, 18 Sep 2010 19:55:10 +0100 Subject: ARM: 6400/1: at91: fix arch_gettimeoffset fallout commit 79e27dc0677b969e2d53b76fa0fa58467cce946a upstream. 5cfc8ee0bb51 (ARM: convert arm to arch_gettimeoffset()) marked all of at91 AND at91x40 as needing ARCH_USES_GETTIMEOFFSET, and hence no high res timer support / accurate clock_gettime() - But only at91x40 needs it. Signed-off-by: Peter Korsgaard Acked-by: John Stultz Acked-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4824fb4f4019..831acd06b6d7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -273,7 +273,6 @@ config ARCH_AT91 bool "Atmel AT91" select ARCH_REQUIRE_GPIOLIB select HAVE_CLK - select ARCH_USES_GETTIMEOFFSET help This enables support for systems based on the Atmel AT91RM9200, AT91SAM9 and AT91CAP9 processors. -- cgit v1.2.3 From c1e962e493031fce0a7f15ded4fb16e94d35ac90 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Thu, 16 Sep 2010 17:57:17 +0100 Subject: ARM: 6395/1: VExpress: Set bit 22 in the PL310 (cache controller) AuxCtlr register commit 1a8e41cd672f894bbd74874eac601e6cedf838fb upstream. Clearing bit 22 in the PL310 Auxiliary Control register (shared attribute override enable) has the side effect of transforming Normal Shared Non-cacheable reads into Cacheable no-allocate reads. Coherent DMA buffers in Linux always have a Cacheable alias via the kernel linear mapping and the processor can speculatively load cache lines into the PL310 controller. With bit 22 cleared, Non-cacheable reads would unexpectedly hit such cache lines leading to buffer corruption. Cc: Nicolas Pitre Signed-off-by: Catalin Marinas Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-vexpress/ct-ca9x4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 6353459bb567..d6dd6f62ba75 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -225,7 +225,7 @@ static void ct_ca9x4_init(void) int i; #ifdef CONFIG_CACHE_L2X0 - l2x0_init(MMIO_P2V(CT_CA9X4_L2CC), 0x00000000, 0xfe0fffff); + l2x0_init(MMIO_P2V(CT_CA9X4_L2CC), 0x00400000, 0xfe0fffff); #endif clkdev_add_table(lookups, ARRAY_SIZE(lookups)); -- cgit v1.2.3 From a035671ad3092e51c5c1d92b39a2ef196b5ab83a Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Fri, 3 Sep 2010 06:57:19 -0300 Subject: V4L/DVB: gspca - main: Fix a crash of some webcams on ARM arch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 882787ff8fdeb0be790547ee9b22b281095e95da upstream. When plugging some webcams on ARM, the system crashes. This is because we alloc buffer for an urb through usb_buffer_alloc, the alloced buffer is already in DMA coherent region, so we should set the flag of this urb to URB_NO_TRANSFER_DMA_MAP, otherwise when we submit this urb, the hcd core will handle this address as an non-DMA address and call dma_map_single/sg to map it. On arm architecture, dma_map_single a DMA coherent address will be catched by a BUG_ON(). Signed-off-by: Jason Wang Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/gspca/gspca.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 678675bb3652..59aba2434383 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -223,6 +223,7 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, usb_rcvintpipe(dev, ep->bEndpointAddress), buffer, buffer_len, int_irq, (void *)gspca_dev, interval); + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; gspca_dev->int_urb = urb; ret = usb_submit_urb(urb, GFP_KERNEL); if (ret < 0) { -- cgit v1.2.3 From 74352c5c9e2e5c914254d2588876c0c13333c6f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Mon, 13 Sep 2010 05:22:37 -0300 Subject: V4L/DVB: gspca - sn9c20x: Bad transfer size of Bayer images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 04d174e99a6eca2f62b56c10ae1d7d0499d83e9d upstream. As the end of frame marker does not contain any pixel, it must not be transferred. Reported-by: Ivo Jager Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/gspca/sn9c20x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 644a7fd4701a..74a005fad89c 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -2368,8 +2368,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, (data[33] << 10); avg_lum >>= 9; atomic_set(&sd->avg_lum, avg_lum); - gspca_frame_add(gspca_dev, LAST_PACKET, - data, len); + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); return; } if (gspca_dev->last_packet_type == LAST_PACKET) { -- cgit v1.2.3 From 0afe0f1ae5a0c79c690e4f3738ab82613aef5441 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 23 Sep 2010 16:22:05 +0200 Subject: mmc: sdhci-s3c: fix NULL ptr access in sdhci_s3c_remove commit 9320f7cbbdd5febf013b0e91db29189724057738 upstream. If not all clocks have been defined in platform data, the driver will cause a null pointer dereference when it is removed. This patch fixes this issue. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Signed-off-by: Andrew Morton Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/sdhci-s3c.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index ad30f074ee15..76c0ec35b324 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -372,8 +372,10 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) sdhci_remove_host(host, 1); for (ptr = 0; ptr < 3; ptr++) { - clk_disable(sc->clk_bus[ptr]); - clk_put(sc->clk_bus[ptr]); + if (sc->clk_bus[ptr]) { + clk_disable(sc->clk_bus[ptr]); + clk_put(sc->clk_bus[ptr]); + } } clk_disable(sc->clk_io); clk_put(sc->clk_io); -- cgit v1.2.3 From b7dfcb6f10570ebf207207ff7d346078faaacf8e Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 20 Sep 2010 14:33:07 +0200 Subject: x86/amd-iommu: Set iommu configuration flags in enable-loop commit e9bf51971157e367aabfc111a8219db010f69cd4 upstream. This patch moves the setting of the configuration and feature flags out out the acpi table parsing path and moves it into the iommu-enable path. This is needed to reliably fix resume-from-s3. Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/amd_iommu_types.h | 3 +++ arch/x86/kernel/amd_iommu_init.c | 49 +++++++++++++++++++--------------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h index 7014e88bc779..ef2d5cd7d7e7 100644 --- a/arch/x86/include/asm/amd_iommu_types.h +++ b/arch/x86/include/asm/amd_iommu_types.h @@ -368,6 +368,9 @@ struct amd_iommu { /* capabilities of that IOMMU read from ACPI */ u32 cap; + /* flags read from acpi table */ + u8 acpi_flags; + /* * Capability pointer. There could be more than one IOMMU per PCI * device function if there are more than one AMD IOMMU capability diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 3cc63e2b8dd4..85e9817ead43 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -649,29 +649,9 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, struct ivhd_entry *e; /* - * First set the recommended feature enable bits from ACPI - * into the IOMMU control registers + * First save the recommended feature enable bits from ACPI */ - h->flags & IVHD_FLAG_HT_TUN_EN_MASK ? - iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) : - iommu_feature_disable(iommu, CONTROL_HT_TUN_EN); - - h->flags & IVHD_FLAG_PASSPW_EN_MASK ? - iommu_feature_enable(iommu, CONTROL_PASSPW_EN) : - iommu_feature_disable(iommu, CONTROL_PASSPW_EN); - - h->flags & IVHD_FLAG_RESPASSPW_EN_MASK ? - iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) : - iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN); - - h->flags & IVHD_FLAG_ISOC_EN_MASK ? - iommu_feature_enable(iommu, CONTROL_ISOC_EN) : - iommu_feature_disable(iommu, CONTROL_ISOC_EN); - - /* - * make IOMMU memory accesses cache coherent - */ - iommu_feature_enable(iommu, CONTROL_COHERENT_EN); + iommu->acpi_flags = h->flags; /* * Done. Now parse the device entries @@ -1116,6 +1096,30 @@ static void init_device_table(void) } } +static void iommu_init_flags(struct amd_iommu *iommu) +{ + iommu->acpi_flags & IVHD_FLAG_HT_TUN_EN_MASK ? + iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) : + iommu_feature_disable(iommu, CONTROL_HT_TUN_EN); + + iommu->acpi_flags & IVHD_FLAG_PASSPW_EN_MASK ? + iommu_feature_enable(iommu, CONTROL_PASSPW_EN) : + iommu_feature_disable(iommu, CONTROL_PASSPW_EN); + + iommu->acpi_flags & IVHD_FLAG_RESPASSPW_EN_MASK ? + iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) : + iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN); + + iommu->acpi_flags & IVHD_FLAG_ISOC_EN_MASK ? + iommu_feature_enable(iommu, CONTROL_ISOC_EN) : + iommu_feature_disable(iommu, CONTROL_ISOC_EN); + + /* + * make IOMMU memory accesses cache coherent + */ + iommu_feature_enable(iommu, CONTROL_COHERENT_EN); +} + /* * This function finally enables all IOMMUs found in the system after * they have been initialized @@ -1126,6 +1130,7 @@ static void enable_iommus(void) for_each_iommu(iommu) { iommu_disable(iommu); + iommu_init_flags(iommu); iommu_set_device_table(iommu); iommu_enable_command_buffer(iommu); iommu_enable_event_buffer(iommu); -- cgit v1.2.3 From f686b1e07177ac4370ff25fe2f980c6961476c22 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 23 Sep 2010 16:12:48 +0200 Subject: x86/amd-iommu: Fix rounding-bug in __unmap_single commit 04e0463e088b41060c08c255eb0d3278a504f094 upstream. In the __unmap_single function the dma_addr is rounded down to a page boundary before the dma pages are unmapped. The address is later also used to flush the TLB entries for that mapping. But without the offset into the dma page the amount of pages to flush might be miscalculated in the TLB flushing path. This patch fixes this bug by using the original address to flush the TLB. Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/amd_iommu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 0d20286d78c6..4424c73ba01e 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -1953,6 +1953,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom, size_t size, int dir) { + dma_addr_t flush_addr; dma_addr_t i, start; unsigned int pages; @@ -1960,6 +1961,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom, (dma_addr + size > dma_dom->aperture_size)) return; + flush_addr = dma_addr; pages = iommu_num_pages(dma_addr, size, PAGE_SIZE); dma_addr &= PAGE_MASK; start = dma_addr; @@ -1974,7 +1976,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom, dma_ops_free_addresses(dma_dom, dma_addr, pages); if (amd_iommu_unmap_flush || dma_dom->need_flush) { - iommu_flush_pages(&dma_dom->domain, dma_addr, size); + iommu_flush_pages(&dma_dom->domain, flush_addr, size); dma_dom->need_flush = false; } } -- cgit v1.2.3 From 1cd864ee52f2768c2701230b2d86dd9244947488 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 23 Sep 2010 15:15:19 +0200 Subject: x86/amd-iommu: Work around S3 BIOS bug commit 4c894f47bb49284008073d351c0ddaac8860864e upstream. This patch adds a workaround for an IOMMU BIOS problem to the AMD IOMMU driver. The result of the bug is that the IOMMU does not execute commands anymore when the system comes out of the S3 state resulting in system failure. The bug in the BIOS is that is does not restore certain hardware specific registers correctly. This workaround reads out the contents of these registers at boot time and restores them on resume from S3. The workaround is limited to the specific IOMMU chipset where this problem occurs. Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/amd_iommu_proto.h | 6 ++++++ arch/x86/include/asm/amd_iommu_types.h | 9 +++++++++ arch/x86/kernel/amd_iommu_init.c | 18 ++++++++++++++++++ include/linux/pci_ids.h | 3 +++ 4 files changed, 36 insertions(+) diff --git a/arch/x86/include/asm/amd_iommu_proto.h b/arch/x86/include/asm/amd_iommu_proto.h index d2544f1d705d..cb030374b90a 100644 --- a/arch/x86/include/asm/amd_iommu_proto.h +++ b/arch/x86/include/asm/amd_iommu_proto.h @@ -38,4 +38,10 @@ static inline void amd_iommu_stats_init(void) { } #endif /* !CONFIG_AMD_IOMMU_STATS */ +static inline bool is_rd890_iommu(struct pci_dev *pdev) +{ + return (pdev->vendor == PCI_VENDOR_ID_ATI) && + (pdev->device == PCI_DEVICE_ID_RD890_IOMMU); +} + #endif /* _ASM_X86_AMD_IOMMU_PROTO_H */ diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h index ef2d5cd7d7e7..08616180deaf 100644 --- a/arch/x86/include/asm/amd_iommu_types.h +++ b/arch/x86/include/asm/amd_iommu_types.h @@ -414,6 +414,15 @@ struct amd_iommu { /* default dma_ops domain for that IOMMU */ struct dma_ops_domain *default_dom; + + /* + * This array is required to work around a potential BIOS bug. + * The BIOS may miss to restore parts of the PCI configuration + * space when the system resumes from S3. The result is that the + * IOMMU does not execute commands anymore which leads to system + * failure. + */ + u32 cache_cfg[4]; }; /* diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 85e9817ead43..5a170cbbbed8 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -632,6 +632,13 @@ static void __init init_iommu_from_pci(struct amd_iommu *iommu) iommu->last_device = calc_devid(MMIO_GET_BUS(range), MMIO_GET_LD(range)); iommu->evt_msi_num = MMIO_MSI_NUM(misc); + + if (is_rd890_iommu(iommu->dev)) { + pci_read_config_dword(iommu->dev, 0xf0, &iommu->cache_cfg[0]); + pci_read_config_dword(iommu->dev, 0xf4, &iommu->cache_cfg[1]); + pci_read_config_dword(iommu->dev, 0xf8, &iommu->cache_cfg[2]); + pci_read_config_dword(iommu->dev, 0xfc, &iommu->cache_cfg[3]); + } } /* @@ -1120,6 +1127,16 @@ static void iommu_init_flags(struct amd_iommu *iommu) iommu_feature_enable(iommu, CONTROL_COHERENT_EN); } +static void iommu_apply_quirks(struct amd_iommu *iommu) +{ + if (is_rd890_iommu(iommu->dev)) { + pci_write_config_dword(iommu->dev, 0xf0, iommu->cache_cfg[0]); + pci_write_config_dword(iommu->dev, 0xf4, iommu->cache_cfg[1]); + pci_write_config_dword(iommu->dev, 0xf8, iommu->cache_cfg[2]); + pci_write_config_dword(iommu->dev, 0xfc, iommu->cache_cfg[3]); + } +} + /* * This function finally enables all IOMMUs found in the system after * they have been initialized @@ -1130,6 +1147,7 @@ static void enable_iommus(void) for_each_iommu(iommu) { iommu_disable(iommu); + iommu_apply_quirks(iommu); iommu_init_flags(iommu); iommu_set_device_table(iommu); iommu_enable_command_buffer(iommu); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 3bedcc149c84..aa702055cd6e 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -393,6 +393,9 @@ #define PCI_DEVICE_ID_VLSI_82C147 0x0105 #define PCI_DEVICE_ID_VLSI_VAS96011 0x0702 +/* AMD RD890 Chipset */ +#define PCI_DEVICE_ID_RD890_IOMMU 0x5a23 + #define PCI_VENDOR_ID_ADL 0x1005 #define PCI_DEVICE_ID_ADL_2301 0x2301 -- cgit v1.2.3 From f574ccce1edf756c98a7ab5d7a95f84b59c897fe Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 22 Sep 2010 17:07:27 -0700 Subject: tracing/x86: Don't use mcount in pvclock.c commit 9ecd4e1689208afe9b059a5ce1333acb2f42c4d2 upstream. When using a paravirt clock, pvclock.c can be used by sched_clock(), which in turn is used by the tracing mechanism for timestamps, which leads to infinite recursion. Disable mcount/tracing for pvclock.o. Signed-off-by: Jeremy Fitzhardinge LKML-Reference: <4C9A9A3F.4040201@goop.org> Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index e77b22083721..f3f34411c8e3 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -11,6 +11,7 @@ ifdef CONFIG_FUNCTION_TRACER CFLAGS_REMOVE_tsc.o = -pg CFLAGS_REMOVE_rtc.o = -pg CFLAGS_REMOVE_paravirt-spinlocks.o = -pg +CFLAGS_REMOVE_pvclock.o = -pg CFLAGS_REMOVE_ftrace.o = -pg CFLAGS_REMOVE_early_printk.o = -pg endif -- cgit v1.2.3 From b2d8327320ca725b91013838e24fff217d643c77 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 22 Sep 2010 22:22:25 -0400 Subject: tracing/x86: Don't use mcount in kvmclock.c commit 258af47479980d8238a04568b94a4e55aa1cb537 upstream. The guest can use the paravirt clock in kvmclock.c which is used by sched_clock(), which in turn is used by the tracing mechanism for timestamps, which leads to infinite recursion. Disable mcount/tracing for kvmclock.o. Cc: Jeremy Fitzhardinge Cc: Avi Kivity Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index f3f34411c8e3..0357c514fc7f 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -12,6 +12,7 @@ CFLAGS_REMOVE_tsc.o = -pg CFLAGS_REMOVE_rtc.o = -pg CFLAGS_REMOVE_paravirt-spinlocks.o = -pg CFLAGS_REMOVE_pvclock.o = -pg +CFLAGS_REMOVE_kvmclock.o = -pg CFLAGS_REMOVE_ftrace.o = -pg CFLAGS_REMOVE_early_printk.o = -pg endif -- cgit v1.2.3 From 3a50feec3b1ba8db6e682affa63f2e7632537316 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Sat, 2 Oct 2010 17:49:08 -0700 Subject: ksm: fix bad user data when swapping commit 4e31635c367a9e21a43cfbfae4c9deda2e19d1f4 upstream. Building under memory pressure, with KSM on 2.6.36-rc5, collapsed with an internal compiler error: typically indicating an error in swapping. Perhaps there's a timing issue which makes it now more likely, perhaps it's just a long time since I tried for so long: this bug goes back to KSM swapping in 2.6.33. Notice how reuse_swap_page() allows an exclusive page to be reused, but only does SetPageDirty if it can delete it from swap cache right then - if it's currently under Writeback, it has to be left in cache and we don't SetPageDirty, but the page can be reused. Fine, the dirty bit will get set in the pte; but notice how zap_pte_range() does not bother to transfer pte_dirty to page_dirty when unmapping a PageAnon. If KSM chooses to share such a page, it will look like a clean copy of swapcache, and not be written out to swap when its memory is needed; then stale data read back from swap when it's needed again. We could fix this in reuse_swap_page() (or even refuse to reuse a page under writeback), but it's more honest to fix my oversight in KSM's write_protect_page(). Several days of testing on three machines confirms that this fixes the issue they showed. Signed-off-by: Hugh Dickins Cc: Andrew Morton Cc: Andrea Arcangeli Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/ksm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/ksm.c b/mm/ksm.c index 17ee9df378ca..79cd773faa85 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -731,7 +731,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page, if (!ptep) goto out; - if (pte_write(*ptep)) { + if (pte_write(*ptep) || pte_dirty(*ptep)) { pte_t entry; swapped = PageSwapCache(page); @@ -754,7 +754,9 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page, set_pte_at(mm, addr, ptep, entry); goto out_unlock; } - entry = pte_wrprotect(entry); + if (pte_dirty(entry)) + set_page_dirty(page); + entry = pte_mkclean(pte_wrprotect(entry)); set_pte_at_notify(mm, addr, ptep, entry); } *orig_pte = *ptep; -- cgit v1.2.3 From 6cd8e5800457113db9a4f1ee6baf9ef654d48b1d Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Thu, 30 Sep 2010 15:15:30 -0700 Subject: i7core_edac: fix panic in udimm sysfs attributes registration commit 64aab720bdf8771214a7c88872bd8e3194c2d279 upstream. Array of udimm sysfs attributes was not ended with NULL marker, leading to dereference of random memory. EDAC DEBUG: edac_create_mci_instance_attributes: edac_create_mci_instance_attributes() file udimm0 EDAC DEBUG: edac_create_mci_instance_attributes: edac_create_mci_instance_attributes() file udimm1 EDAC DEBUG: edac_create_mci_instance_attributes: edac_create_mci_instance_attributes() file udimm2 BUG: unable to handle kernel NULL pointer dereference at 00000000000001a4 IP: [] edac_create_mci_instance_attributes+0x148/0x1f1 Pid: 1, comm: swapper Not tainted 2.6.36-rc3-nv+ #483 P6T SE/System Product Name RIP: 0010:[] [] edac_create_mci_instance_attributes+0x148/0x1f1 (...) Call Trace: [] edac_create_mci_instance_attributes+0x198/0x1f1 [] edac_create_sysfs_mci_device+0xbb/0x2b2 [] edac_mc_add_mc+0x46b/0x557 [] i7core_probe+0xccf/0xec0 RIP [] edac_create_mci_instance_attributes+0x148/0x1f1 ---[ end trace 20de320855b81d78 ]--- Kernel panic - not syncing: Attempted to kill init! Signed-off-by: Marcin Slusarz Cc: Mauro Carvalho Chehab Acked-by: Doug Thompson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/edac/i7core_edac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index e0187d16dd7c..0fd5b85a0f75 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1140,6 +1140,7 @@ static struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = { ATTR_COUNTER(0), ATTR_COUNTER(1), ATTR_COUNTER(2), + { .attr = { .name = NULL } } }; static struct mcidev_sysfs_group i7core_udimm_counters = { -- cgit v1.2.3 From d7d8fdce55b63cb3a6782f02ce9ec628592d7c4c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 15 Oct 2010 11:12:38 -0700 Subject: v4l1: fix 32-bit compat microcode loading translation commit 3e645d6b485446c54c6745c5e2cf5c528fe4deec upstream. The compat code for the VIDIOCSMICROCODE ioctl is totally buggered. It's only used by the VIDEO_STRADIS driver, and that one is scheduled to staging and eventually removed unless somebody steps up to maintain it (at which point it should use request_firmware() rather than some magic ioctl). So we'll get rid of it eventually. But in the meantime, the compatibility ioctl code is broken, and this tries to get it to at least limp along (even if Mauro suggested just deleting it entirely, which may be the right thing to do - I don't think the compatibility translation code has ever worked unless you were very lucky). Reported-by: Kees Cook Cc: Mauro Carvalho Chehab Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/v4l2-compat-ioctl32.c | 32 ++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index 9004a5fe7643..85b175de3223 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -193,17 +193,24 @@ static int put_video_window32(struct video_window *kp, struct video_window32 __u struct video_code32 { char loadwhat[16]; /* name or tag of file being passed */ compat_int_t datasize; - unsigned char *data; + compat_uptr_t data; }; -static int get_microcode32(struct video_code *kp, struct video_code32 __user *up) +static struct video_code __user *get_microcode32(struct video_code32 *kp) { - if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) || - copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) || - get_user(kp->datasize, &up->datasize) || - copy_from_user(kp->data, up->data, up->datasize)) - return -EFAULT; - return 0; + struct video_code __user *up; + + up = compat_alloc_user_space(sizeof(*up)); + + /* + * NOTE! We don't actually care if these fail. If the + * user address is invalid, the native ioctl will do + * the error handling for us + */ + (void) copy_to_user(up->loadwhat, kp->loadwhat, sizeof(up->loadwhat)); + (void) put_user(kp->datasize, &up->datasize); + (void) put_user(compat_ptr(kp->data), &up->data); + return up; } #define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32) @@ -744,7 +751,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar struct video_tuner vt; struct video_buffer vb; struct video_window vw; - struct video_code vc; + struct video_code32 vc; struct video_audio va; #endif struct v4l2_format v2f; @@ -823,8 +830,11 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar break; case VIDIOCSMICROCODE: - err = get_microcode32(&karg.vc, up); - compatible_arg = 0; + /* Copy the 32-bit "video_code32" to kernel space */ + if (copy_from_user(&karg.vc, up, sizeof(karg.vc))) + return -EFAULT; + /* Convert the 32-bit version to a 64-bit version in user space */ + up = get_microcode32(&karg.vc); break; case VIDIOCSFREQ: -- cgit v1.2.3 From e530826ee487420691ef0882cfbf462959082a7a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 11 Sep 2010 11:37:51 -0300 Subject: V4L/DVB: cx231xx: Avoid an OOPS when card is unknown (card=0) commit c10469c637602c2385e2993d8c730cc44fd47d23 upstream. As reported by: Carlos Americo Domiciano : [ 220.033500] cx231xx v4l2 driver loaded. [ 220.033571] cx231xx #0: New device Conexant Corporation Polaris AV Capturb @ 480 Mbps (1554:5010) with 6 interfaces [ 220.033577] cx231xx #0: registering interface 0 [ 220.033591] cx231xx #0: registering interface 1 [ 220.033654] cx231xx #0: registering interface 6 [ 220.033910] cx231xx #0: Identified as Unknown CX231xx video grabber (card=0) [ 220.033946] BUG: unable to handle kernel NULL pointer dereference at (null) [ 220.033955] IP: [] cx231xx_pre_card_setup+0x5d/0xb0 [cx231xx] Thanks-to: Carlos Americo Domiciano Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/cx231xx/cx231xx-cards.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 6bdc0ef18119..f78c07c53ba0 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -226,14 +226,16 @@ void cx231xx_pre_card_setup(struct cx231xx *dev) dev->board.name, dev->model); /* set the direction for GPIO pins */ - cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1); - cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1); - cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1); + if (dev->board.tuner_gpio) { + cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1); + cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1); + cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1); - /* request some modules if any required */ + /* request some modules if any required */ - /* reset the Tuner */ - cx231xx_gpio_set(dev, dev->board.tuner_gpio); + /* reset the Tuner */ + cx231xx_gpio_set(dev, dev->board.tuner_gpio); + } /* set the mode to Analog mode initially */ cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); -- cgit v1.2.3 From 06deee8ca72d6ebbe1d505f00067c87925e17812 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Mon, 6 Sep 2010 18:26:09 -0300 Subject: V4L/DVB: IR: fix keys beeing stuck down forever commit e0172fd373ab77a83ea952fd6a75c612e1b0bf9e upstream. The logic in ir_timer_keyup was inverted. In case that values aren't equal, the meaning of the time_is_after_eq_jiffies(ir->keyup_jiffies) is that ir->keyup_jiffies is after the the jiffies or equally that that jiffies are before the the ir->keyup_jiffies which is exactly the situation we want to avoid (that the timeout is in the future) Confusing Eh? Signed-off-by: Maxim Levitsky Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/IR/ir-keytable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 94a8577e72eb..78eb8cbc1d53 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -319,7 +319,7 @@ static void ir_timer_keyup(unsigned long cookie) * a keyup event might follow immediately after the keydown. */ spin_lock_irqsave(&ir->keylock, flags); - if (time_is_after_eq_jiffies(ir->keyup_jiffies)) + if (time_is_before_eq_jiffies(ir->keyup_jiffies)) ir_keyup(ir); spin_unlock_irqrestore(&ir->keylock, flags); } -- cgit v1.2.3 From 81e8f58379abbc46f29b7fcba6acfce90e362736 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 3 Sep 2010 10:50:24 -0300 Subject: V4L/DVB: Don't identify PV SBTVD Hybrid as a DibCom device commit 3bfb317f97cfddbbec67bbe8e35ad38af3507397 upstream. As reported by Carlos, Prolink Pixelview SBTVD Hybrid is based on Conexant cx231xx + Fujitsu 86A20S demodulator. However, both shares the same USB ID. So, we need to use USB bcdDevice, in order to properly discover what's the board. We know for sure that bcd 0x100 is used for a dib0700 device, while bcd 0x4001 is used for a cx23102 device. This patch reserves two ranges, the first one from 0x0000-0x3f00 for dib0700, and the second from 0x4000-0x4fff for cx231xx devices. This may need fixes in the future, as we get access to other devices. Thanks-to: Carlos Americo Domiciano Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 2 +- drivers/media/video/cx231xx/Makefile | 1 + drivers/media/video/cx231xx/cx231xx-cards.c | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 800800a9649e..89c0627908c9 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -2081,7 +2081,7 @@ struct usb_device_id dib0700_usb_id_table[] = { /* 60 */{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS_2) }, { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XPVR) }, { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XP) }, - { USB_DEVICE(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD) }, + { USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x000, 0x3f00) }, { USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) }, /* 65 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) }, { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) }, diff --git a/drivers/media/video/cx231xx/Makefile b/drivers/media/video/cx231xx/Makefile index 755dd0ce65ff..6f2b57384488 100644 --- a/drivers/media/video/cx231xx/Makefile +++ b/drivers/media/video/cx231xx/Makefile @@ -11,4 +11,5 @@ EXTRA_CFLAGS += -Idrivers/media/video EXTRA_CFLAGS += -Idrivers/media/common/tuners EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index f78c07c53ba0..f2a4900014bc 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -32,6 +32,7 @@ #include #include +#include "dvb-usb-ids.h" #include "xc5000.h" #include "cx231xx.h" @@ -175,6 +176,8 @@ struct usb_device_id cx231xx_id_table[] = { .driver_info = CX231XX_BOARD_CNXT_RDE_250}, {USB_DEVICE(0x0572, 0x58A1), .driver_info = CX231XX_BOARD_CNXT_RDU_250}, + {USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000,0x4fff), + .driver_info = CX231XX_BOARD_UNKNOWN}, {}, }; -- cgit v1.2.3 From 1a93a2c2bebfc831296f0e4f8a394efac9f9b33f Mon Sep 17 00:00:00 2001 From: Kenneth Waters Date: Tue, 21 Sep 2010 00:58:23 -0700 Subject: Input: joydev - fix JSIOCSAXMAP ioctl commit d2520a426dc3033c00077e923a553fc6c98c7564 upstream. Fixed JSIOCSAXMAP ioctl to update absmap, the map from hardware axis to event axis in addition to abspam. This fixes a regression introduced by 999b874f. Signed-off-by: Kenneth Waters Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/joydev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 34157bb97ed6..f5320b558c73 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -483,6 +483,9 @@ static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev, memcpy(joydev->abspam, abspam, len); + for (i = 0; i < joydev->nabs; i++) + joydev->absmap[joydev->abspam[i]] = i; + out: kfree(abspam); return retval; -- cgit v1.2.3 From df2b79ccc6740db529779198331064351dc87512 Mon Sep 17 00:00:00 2001 From: Aristeu Rozanski Date: Sun, 10 Oct 2010 14:12:33 -0700 Subject: Input: wacom - fix pressure in Cintiq 21UX2 commit ca047fedd89bbb4b79b61e0656a7b799e4e45e6d upstream. Currently the pressure range in Cintiq 21UX2 is limited to half of the supported. This patch fixes the problem. Signed-off-by: Aristeu Rozanski Acked-by: Ping Cheng Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/tablet/wacom_wac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 415f6306105d..8a6a2a1733c4 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -409,8 +409,10 @@ static void wacom_intuos_general(struct wacom_wac *wacom) /* general pen packet */ if ((data[1] & 0xb8) == 0xa0) { t = (data[6] << 2) | ((data[7] >> 6) & 3); - if (features->type >= INTUOS4S && features->type <= INTUOS4L) + if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || + features->type == WACOM_21UX2) { t = (t << 1) | (data[1] & 1); + } input_report_abs(input, ABS_PRESSURE, t); input_report_abs(input, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); -- cgit v1.2.3 From b6df308f73dee36d4c1810ede94068a78455c485 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 13 Oct 2010 15:43:10 -0700 Subject: ioat2: fix performance regression commit c50a898fd4e736623ee175920db056194e0bb483 upstream. Commit 0793448 "DMAENGINE: generic channel status v2" changed the interface for how dma channel progress is retrieved. It inadvertently exported an internal helper function ioat_tx_status() instead of ioat_dma_tx_status(). The latter polls the hardware to get the latest completion state, while the helper just evaluates the current state without touching hardware. The effect is that we end up waiting for completion timeouts or descriptor allocation errors before the completion state is updated. iperf (before fix): [SUM] 0.0-41.3 sec 364 MBytes 73.9 Mbits/sec iperf (after fix): [SUM] 0.0- 4.5 sec 499 MBytes 940 Mbits/sec This is a regression starting with 2.6.35. Cc: Dave Jiang Cc: Jesse Brandeburg Cc: Linus Walleij Cc: Maciej Sosnowski Reported-by: Richard Scobie Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/dma/ioat/dma_v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c index 216f9d383b5b..effd140fc042 100644 --- a/drivers/dma/ioat/dma_v2.c +++ b/drivers/dma/ioat/dma_v2.c @@ -879,7 +879,7 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca) dma->device_issue_pending = ioat2_issue_pending; dma->device_alloc_chan_resources = ioat2_alloc_chan_resources; dma->device_free_chan_resources = ioat2_free_chan_resources; - dma->device_tx_status = ioat_tx_status; + dma->device_tx_status = ioat_dma_tx_status; err = ioat_probe(device); if (err) -- cgit v1.2.3 From 22d59a19e77a8b8c2d1b83fc98272cc095ac92b7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 24 Sep 2010 11:20:47 +0200 Subject: mac80211: fix use-after-free commit cd87a2d3a33d75a646f1aa1aa2ee5bf712d6f963 upstream. commit 8c0c709eea5cbab97fb464cd68b06f24acc58ee1 Author: Johannes Berg Date: Wed Nov 25 17:46:15 2009 +0100 mac80211: move cmntr flag out of rx flags moved the CMTR flag into the skb's status, and in doing so introduced a use-after-free -- when the skb has been handed to cooked monitors the status setting will touch now invalid memory. Additionally, moving it there has effectively discarded the optimisation -- since the bit is only ever set on freed SKBs, and those were a copy, it could never be checked. For the current release, fixing this properly is a bit too involved, so let's just remove the problematic code and leave userspace with one copy of each frame for each virtual interface. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/rx.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index be9abc2e6348..af775e9bf60a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2156,9 +2156,6 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, struct net_device *prev_dev = NULL; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); - if (status->flag & RX_FLAG_INTERNAL_CMTR) - goto out_free_skb; - if (skb_headroom(skb) < sizeof(*rthdr) && pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) goto out_free_skb; @@ -2217,7 +2214,6 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, } else goto out_free_skb; - status->flag |= RX_FLAG_INTERNAL_CMTR; return; out_free_skb: -- cgit v1.2.3 From 8268a8d756bd63b9f68ee6fbe9cad0548134b2ca Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 28 Sep 2010 23:20:23 +0200 Subject: x86, hpet: Fix bogus error check in hpet_assign_irq() commit 021989622810b02aab4b24f91e1f5ada2b654579 upstream. create_irq() returns -1 if the interrupt allocation failed, but the code checks for irq == 0. Use create_irq_nr() instead. Signed-off-by: Thomas Gleixner Cc: Venkatesh Pallipadi LKML-Reference: Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/hpet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 7cd18862f041..917c66fca56d 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -507,7 +507,7 @@ static int hpet_assign_irq(struct hpet_dev *dev) { unsigned int irq; - irq = create_irq(); + irq = create_irq_nr(0, -1); if (!irq) return -EINVAL; -- cgit v1.2.3 From 6af2c5f5ab721df7e7b36b939fa11591264ade32 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 28 Sep 2010 20:57:19 +0200 Subject: x86, irq: Plug memory leak in sparse irq commit 1cf180c94e9166cda083ff65333883ab3648e852 upstream. free_irq_cfg() is not freeing the cpumask_vars in irq_cfg. Fixing this triggers a use after free caused by the fact that copying struct irq_cfg is done with memcpy, which copies the pointer not the cpumask. Fix both places. Signed-off-by: Thomas Gleixner Cc: Yinghai Lu LKML-Reference: Signed-off-by: Thomas Gleixner Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/apic/io_apic.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index f1efebaf5510..5c5b8f3dddb5 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -306,14 +306,19 @@ void arch_init_copy_chip_data(struct irq_desc *old_desc, old_cfg = old_desc->chip_data; - memcpy(cfg, old_cfg, sizeof(struct irq_cfg)); + cfg->vector = old_cfg->vector; + cfg->move_in_progress = old_cfg->move_in_progress; + cpumask_copy(cfg->domain, old_cfg->domain); + cpumask_copy(cfg->old_domain, old_cfg->old_domain); init_copy_irq_2_pin(old_cfg, cfg, node); } -static void free_irq_cfg(struct irq_cfg *old_cfg) +static void free_irq_cfg(struct irq_cfg *cfg) { - kfree(old_cfg); + free_cpumask_var(cfg->domain); + free_cpumask_var(cfg->old_domain); + kfree(cfg); } void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc) -- cgit v1.2.3 From 84602dccfecbc66a791cdd1f2f32b4481ce67586 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 15 Oct 2010 12:56:21 +0200 Subject: ubd: fix incorrect sector handling during request restart commit 47526903feb52f4c26a6350370bdf74e337fcdb1 upstream. Commit f81f2f7c (ubd: drop unnecessary rq->sector manipulation) dropped request->sector manipulation in preparation for global request handling cleanup; unfortunately, it incorrectly assumed that the updated sector wasn't being used. ubd tries to issue as many requests as possible to io_thread. When issuing fails due to memory pressure or other reasons, the device is put on the restart list and issuing stops. On IO completion, devices on the restart list are scanned and IO issuing is restarted. ubd issues IOs sg-by-sg and issuing can be stopped in the middle of a request, so each device on the restart queue needs to remember where to restart in its current request. ubd needs to keep track of the issue position itself because, * blk_rq_pos(req) is now updated by the block layer to keep track of _completion_ position. * Multiple io_req's for the current request may be in flight, so it's difficult to tell where blk_rq_pos(req) currently is. Add ubd->rq_pos to keep track of the issue position and use it to correctly restart io_req issue. Signed-off-by: Tejun Heo Reported-by: Richard Weinberger Tested-by: Richard Weinberger Tested-by: Chris Frey Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- arch/um/drivers/ubd_kern.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index da992a3ad6b7..3d63b832c39d 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -162,6 +162,7 @@ struct ubd { struct scatterlist sg[MAX_SG]; struct request *request; int start_sg, end_sg; + sector_t rq_pos; }; #define DEFAULT_COW { \ @@ -186,6 +187,7 @@ struct ubd { .request = NULL, \ .start_sg = 0, \ .end_sg = 0, \ + .rq_pos = 0, \ } /* Protected by ubd_lock */ @@ -1223,7 +1225,6 @@ static void do_ubd_request(struct request_queue *q) { struct io_thread_req *io_req; struct request *req; - sector_t sector; int n; while(1){ @@ -1234,12 +1235,12 @@ static void do_ubd_request(struct request_queue *q) return; dev->request = req; + dev->rq_pos = blk_rq_pos(req); dev->start_sg = 0; dev->end_sg = blk_rq_map_sg(q, req, dev->sg); } req = dev->request; - sector = blk_rq_pos(req); while(dev->start_sg < dev->end_sg){ struct scatterlist *sg = &dev->sg[dev->start_sg]; @@ -1251,10 +1252,9 @@ static void do_ubd_request(struct request_queue *q) return; } prepare_request(req, io_req, - (unsigned long long)sector << 9, + (unsigned long long)dev->rq_pos << 9, sg->offset, sg->length, sg_page(sg)); - sector += sg->length >> 9; n = os_write_file(thread_fd, &io_req, sizeof(struct io_thread_req *)); if(n != sizeof(struct io_thread_req *)){ @@ -1267,6 +1267,7 @@ static void do_ubd_request(struct request_queue *q) return; } + dev->rq_pos += sg->length >> 9; dev->start_sg++; } dev->end_sg = 0; -- cgit v1.2.3 From c4cb1dd93619b45e8d0295bbcb83389195ce66fb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 10 Oct 2010 19:33:52 +0200 Subject: OSS: soundcard: locking bug in sound_ioctl() commit d4cfa4d12f46e2520f4c1d1a92e891ce068b7464 upstream. We shouldn't return directly here because we're still holding the &soundcard_mutex. This bug goes all the way back to the start of git. It's strange that no one has complained about it as a runtime bug. Signed-off-by: Dan Carpenter Acked-by: Arnd Bergmann Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/oss/soundcard.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index 2d9c51312622..19ce86d445c2 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c @@ -389,11 +389,11 @@ static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case SND_DEV_DSP: case SND_DEV_DSP16: case SND_DEV_AUDIO: - return audio_ioctl(dev, file, cmd, p); + ret = audio_ioctl(dev, file, cmd, p); break; case SND_DEV_MIDIN: - return MIDIbuf_ioctl(dev, file, cmd, p); + ret = MIDIbuf_ioctl(dev, file, cmd, p); break; } -- cgit v1.2.3 From 39a1d13e238b714c8713fd9739141b552724d1fe Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Sat, 9 Oct 2010 12:12:13 +1030 Subject: virtio-blk: fix request leak. commit e4c4776dea9fd0295ebb3b215599d52938d6d7a3 upstream. Must drop reference taken by blk_make_request(). Signed-off-by: Mike Snitzer Signed-off-by: Rusty Russell Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/block/virtio_blk.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 258bc2ae2885..3c108bc71e50 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -203,6 +203,7 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str) struct virtio_blk *vblk = disk->private_data; struct request *req; struct bio *bio; + int err; bio = bio_map_kern(vblk->disk->queue, id_str, VIRTIO_BLK_ID_BYTES, GFP_KERNEL); @@ -216,7 +217,10 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str) } req->cmd_type = REQ_TYPE_SPECIAL; - return blk_execute_rq(vblk->disk->queue, vblk->disk, req, false); + err = blk_execute_rq(vblk->disk->queue, vblk->disk, req, false); + blk_put_request(req); + + return err; } static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, -- cgit v1.2.3 From 02ee32edab40e81b2af0149a8fb86986fc5ac9e7 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 12 Oct 2010 12:06:43 -0400 Subject: ring-buffer: Fix typo of time extends per page commit d01343244abdedd18303d0323b518ed9cdcb1988 upstream. Time stamps for the ring buffer are created by the difference between two events. Each page of the ring buffer holds a full 64 bit timestamp. Each event has a 27 bit delta stamp from the last event. The unit of time is nanoseconds, so 27 bits can hold ~134 milliseconds. If two events happen more than 134 milliseconds apart, a time extend is inserted to add more bits for the delta. The time extend has 59 bits, which is good for ~18 years. Currently the time extend is committed separately from the event. If an event is discarded before it is committed, due to filtering, the time extend still exists. If all events are being filtered, then after ~134 milliseconds a new time extend will be added to the buffer. This can only happen till the end of the page. Since each page holds a full timestamp, there is no reason to add a time extend to the beginning of a page. Time extends can only fill a page that has actual data at the beginning, so there is no fear that time extends will fill more than a page without any data. When reading an event, a loop is made to skip over time extends since they are only used to maintain the time stamp and are never given to the caller. As a paranoid check to prevent the loop running forever, with the knowledge that time extends may only fill a page, a check is made that tests the iteration of the loop, and if the iteration is more than the number of time extends that can fit in a page a warning is printed and the ring buffer is disabled (all of ftrace is also disabled with it). There is another event type that is called a TIMESTAMP which can hold 64 bits of data in the theoretical case that two events happen 18 years apart. This code has not been implemented, but the name of this event exists, as well as the structure for it. The size of a TIMESTAMP is 16 bytes, where as a time extend is only 8 bytes. The macro used to calculate how many time extends can fit on a page used the TIMESTAMP size instead of the time extend size cutting the amount in half. The following test case can easily trigger the warning since we only need to have half the page filled with time extends to trigger the warning: # cd /sys/kernel/debug/tracing/ # echo function > current_tracer # echo 'common_pid < 0' > events/ftrace/function/filter # echo > trace # echo 1 > trace_marker # sleep 120 # cat trace Enabling the function tracer and then setting the filter to only trace functions where the process id is negative (no events), then clearing the trace buffer to ensure that we have nothing in the buffer, then write to trace_marker to add an event to the beginning of a page, sleep for 2 minutes (only 35 seconds is probably needed, but this guarantees the bug), and then finally reading the trace which will trigger the bug. This patch fixes the typo and prevents the false positive of that warning. Reported-by: Hans J. Koch Tested-by: Hans J. Koch Cc: Thomas Gleixner Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/trace/ring_buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 5ec8f1d1480e..6cd7334ee01e 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -405,7 +405,7 @@ static inline int test_time_stamp(u64 delta) #define BUF_MAX_DATA_SIZE (BUF_PAGE_SIZE - (sizeof(u32) * 2)) /* Max number of timestamps that can fit on a page */ -#define RB_TIMESTAMPS_PER_PAGE (BUF_PAGE_SIZE / RB_LEN_TIME_STAMP) +#define RB_TIMESTAMPS_PER_PAGE (BUF_PAGE_SIZE / RB_LEN_TIME_EXTEND) int ring_buffer_print_page_header(struct trace_seq *s) { -- cgit v1.2.3 From 677c3a487715716e4c8e61a882e0680578d90103 Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Fri, 17 Sep 2010 23:33:51 +0200 Subject: dmaengine: fix interrupt clearing for mv_xor commit cc60f8878eab892c03d06b10f389232b9b66bd83 upstream. When using simultaneously the two DMA channels on a same engine, some transfers are never completed. For example, an endless lock can occur while writing heavily on a RAID5 array (with async-tx offload support enabled). Note that this issue can also be reproduced by using the DMA test client. On a same engine, the interrupt cause register is shared between two DMA channels. This patch make sure that the cause bit is only cleared for the requested channel. Signed-off-by: Simon Guinot Tested-by: Luc Saillard Acked-by: saeed bishara Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/dma/mv_xor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 86c5ae9fde34..411d5bf50fc4 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -162,7 +162,7 @@ static int mv_is_err_intr(u32 intr_cause) static void mv_xor_device_clear_eoc_cause(struct mv_xor_chan *chan) { - u32 val = (1 << (1 + (chan->idx * 16))); + u32 val = ~(1 << (chan->idx * 16)); dev_dbg(chan->device->common.dev, "%s, val 0x%08x\n", __func__, val); __raw_writel(val, XOR_INTR_CAUSE(chan)); } -- cgit v1.2.3 From 6c05813f0d8e05b2b6643843100b02687dd03929 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 2 Oct 2010 15:59:17 +0200 Subject: drivers/gpu/drm/i915/i915_gem.c: Add missing error handling code commit 929f49bf225b1b6cd04d0a7b9c0f7377d9131220 upstream. Extend the error handling code with operations found in other nearby error handling code A simplified version of the sematic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r exists@ @r@ statement S1,S2,S3; constant C1,C2,C3; @@ *if (...) {... S1 return -C1;} ... *if (...) {... when != S1 return -C2;} ... *if (...) {... S1 return -C3;} // Signed-off-by: Julia Lawall Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_gem.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 06f82382ce6d..9dc220f2e4dd 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3367,6 +3367,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, (int) reloc->offset, reloc->read_domains, reloc->write_domain); + drm_gem_object_unreference(target_obj); + i915_gem_object_unpin(obj); return -EINVAL; } if (reloc->write_domain & I915_GEM_DOMAIN_CPU || -- cgit v1.2.3 From eafe9c354fde7597834d45a04f79e9057d24ae93 Mon Sep 17 00:00:00 2001 From: Salman Qazi Date: Tue, 12 Oct 2010 07:25:19 -0700 Subject: hrtimer: Preserve timer state in remove_hrtimer() commit f13d4f979c518119bba5439dd2364d76d31dcd3f upstream. The race is described as follows: CPU X CPU Y remove_hrtimer // state & QUEUED == 0 timer->state = CALLBACK unlock timer base timer->f(n) //very long hrtimer_start lock timer base remove_hrtimer // no effect hrtimer_enqueue timer->state = CALLBACK | QUEUED unlock timer base hrtimer_start lock timer base remove_hrtimer mode = INACTIVE // CALLBACK bit lost! switch_hrtimer_base CALLBACK bit not set: timer->base changes to a different CPU. lock this CPU's timer base The bug was introduced with commit ca109491f (hrtimer: removing all ur callback modes) in 2.6.29 [ tglx: Feed new state via local variable and add a comment. ] Signed-off-by: Salman Qazi Cc: akpm@linux-foundation.org Cc: Peter Zijlstra LKML-Reference: <20101012142351.8485.21823.stgit@dungbeetle.mtv.corp.google.com> Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/hrtimer.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 5c69e996bd0f..21e0c5e468b6 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -936,6 +936,7 @@ static inline int remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base) { if (hrtimer_is_queued(timer)) { + unsigned long state; int reprogram; /* @@ -949,8 +950,13 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base) debug_deactivate(timer); timer_stats_hrtimer_clear_start_info(timer); reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases); - __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE, - reprogram); + /* + * We must preserve the CALLBACK state flag here, + * otherwise we could move the timer base in + * switch_hrtimer_base. + */ + state = timer->state & HRTIMER_STATE_CALLBACK; + __remove_hrtimer(timer, base, state, reprogram); return 1; } return 0; @@ -1237,6 +1243,9 @@ static void __run_hrtimer(struct hrtimer *timer, ktime_t *now) BUG_ON(timer->state != HRTIMER_STATE_CALLBACK); enqueue_hrtimer(timer, base); } + + WARN_ON_ONCE(!(timer->state & HRTIMER_STATE_CALLBACK)); + timer->state &= ~HRTIMER_STATE_CALLBACK; } -- cgit v1.2.3 From 738757938c56703f8568b4628291361b8655bb79 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Thu, 30 Sep 2010 14:14:22 +0200 Subject: i2c-pca: Fix waitforcompletion() return value commit 6abb930af064fb1cf4177d32e2c7bfb89eee0fe5 upstream. ret is still -1, if during the polling read_byte() returns at once with I2C_PCA_CON_SI set. So ret > 0 would lead *_waitforcompletion() to return 0, in spite of the proper behavior. The routine was rewritten, so that ret has always a proper value, before returning. Signed-off-by: Yegor Yefremov Reviewed-by: Wolfram Sang Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-pca-isa.c | 12 ++++++++---- drivers/i2c/busses/i2c-pca-platform.c | 11 +++++++---- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index bbd77603a417..29933f87d8fa 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -71,8 +71,8 @@ static int pca_isa_readbyte(void *pd, int reg) static int pca_isa_waitforcompletion(void *pd) { - long ret = ~0; unsigned long timeout; + long ret; if (irq > -1) { ret = wait_event_timeout(pca_wait, @@ -81,11 +81,15 @@ static int pca_isa_waitforcompletion(void *pd) } else { /* Do polling */ timeout = jiffies + pca_isa_ops.timeout; - while (((pca_isa_readbyte(pd, I2C_PCA_CON) - & I2C_PCA_CON_SI) == 0) - && (ret = time_before(jiffies, timeout))) + do { + ret = time_before(jiffies, timeout); + if (pca_isa_readbyte(pd, I2C_PCA_CON) + & I2C_PCA_CON_SI) + break; udelay(100); + } while (ret); } + return ret > 0; } diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index ef5c78487eb7..5f6d7f89e225 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -80,8 +80,8 @@ static void i2c_pca_pf_writebyte32(void *pd, int reg, int val) static int i2c_pca_pf_waitforcompletion(void *pd) { struct i2c_pca_pf_data *i2c = pd; - long ret = ~0; unsigned long timeout; + long ret; if (i2c->irq) { ret = wait_event_timeout(i2c->wait, @@ -90,10 +90,13 @@ static int i2c_pca_pf_waitforcompletion(void *pd) } else { /* Do polling */ timeout = jiffies + i2c->adap.timeout; - while (((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) - & I2C_PCA_CON_SI) == 0) - && (ret = time_before(jiffies, timeout))) + do { + ret = time_before(jiffies, timeout); + if (i2c->algo_data.read_byte(i2c, I2C_PCA_CON) + & I2C_PCA_CON_SI) + break; udelay(100); + } while (ret); } return ret > 0; -- cgit v1.2.3 From cd1bbdfed8ff5047d96ed27a3ee7b881069daf03 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 30 Sep 2010 15:15:37 -0700 Subject: reiserfs: fix dependency inversion between inode and reiserfs mutexes commit 3f259d092c7a2fdf217823e8f1838530adb0cdb0 upstream. The reiserfs mutex already depends on the inode mutex, so we can't lock the inode mutex in reiserfs_unpack() without using the safe locking API, because reiserfs_unpack() is always called with the reiserfs mutex locked. This fixes: ======================================================= [ INFO: possible circular locking dependency detected ] 2.6.35c #13 ------------------------------------------------------- lilo/1606 is trying to acquire lock: (&sb->s_type->i_mutex_key#8){+.+.+.}, at: [] reiserfs_unpack+0x60/0x110 [reiserfs] but task is already holding lock: (&REISERFS_SB(s)->lock){+.+.+.}, at: [] reiserfs_write_lock+0x28/0x40 [reiserfs] which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (&REISERFS_SB(s)->lock){+.+.+.}: [] lock_acquire+0x67/0x80 [] __mutex_lock_common+0x4d/0x410 [] mutex_lock_nested+0x18/0x20 [] reiserfs_write_lock+0x28/0x40 [reiserfs] [] reiserfs_lookup_privroot+0x2a/0x90 [reiserfs] [] reiserfs_fill_super+0x941/0xe60 [reiserfs] [] get_sb_bdev+0x117/0x170 [] get_super_block+0x21/0x30 [reiserfs] [] vfs_kern_mount+0x6a/0x1b0 [] do_kern_mount+0x39/0xe0 [] do_mount+0x340/0x790 [] sys_mount+0x84/0xb0 [] syscall_call+0x7/0xb -> #0 (&sb->s_type->i_mutex_key#8){+.+.+.}: [] __lock_acquire+0x1026/0x1180 [] lock_acquire+0x67/0x80 [] __mutex_lock_common+0x4d/0x410 [] mutex_lock_nested+0x18/0x20 [] reiserfs_unpack+0x60/0x110 [reiserfs] [] reiserfs_ioctl+0x272/0x320 [reiserfs] [] vfs_ioctl+0x28/0xa0 [] do_vfs_ioctl+0x32d/0x5c0 [] sys_ioctl+0x63/0x70 [] syscall_call+0x7/0xb other info that might help us debug this: 1 lock held by lilo/1606: #0: (&REISERFS_SB(s)->lock){+.+.+.}, at: [] reiserfs_write_lock+0x28/0x40 [reiserfs] stack backtrace: Pid: 1606, comm: lilo Not tainted 2.6.35c #13 Call Trace: [] __lock_acquire+0x1026/0x1180 [] lock_acquire+0x67/0x80 [] __mutex_lock_common+0x4d/0x410 [] mutex_lock_nested+0x18/0x20 [] reiserfs_unpack+0x60/0x110 [reiserfs] [] reiserfs_ioctl+0x272/0x320 [reiserfs] [] vfs_ioctl+0x28/0xa0 [] do_vfs_ioctl+0x32d/0x5c0 [] sys_ioctl+0x63/0x70 [] syscall_call+0x7/0xb Reported-by: Jarek Poplawski Tested-by: Jarek Poplawski Signed-off-by: Frederic Weisbecker Cc: Jeff Mahoney Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/reiserfs/ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index f53505de0712..679d5029f50f 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c @@ -188,7 +188,7 @@ int reiserfs_unpack(struct inode *inode, struct file *filp) /* we need to make sure nobody is changing the file size beneath ** us */ - mutex_lock(&inode->i_mutex); + reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb); reiserfs_write_lock(inode->i_sb); write_from = inode->i_size & (blocksize - 1); -- cgit v1.2.3 From 5ecce9b3a94f2faa4ee0528662960ae9308aff37 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 30 Sep 2010 15:15:38 -0700 Subject: reiserfs: fix unwanted reiserfs lock recursion commit 9d8117e72bf453dd9d85e0cd322ce4a0f8bccbc0 upstream. Prevent from recursively locking the reiserfs lock in reiserfs_unpack() because we may call journal_begin() that requires the lock to be taken only once, otherwise it won't be able to release the lock while taking other mutexes, ending up in inverted dependencies between the journal mutex and the reiserfs lock for example. This fixes: ======================================================= [ INFO: possible circular locking dependency detected ] 2.6.35.4.4a #3 ------------------------------------------------------- lilo/1620 is trying to acquire lock: (&journal->j_mutex){+.+...}, at: [] do_journal_begin_r+0x7f/0x340 [reiserfs] but task is already holding lock: (&REISERFS_SB(s)->lock){+.+.+.}, at: [] reiserfs_write_lock+0x28/0x40 [reiserfs] which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (&REISERFS_SB(s)->lock){+.+.+.}: [] lock_acquire+0x67/0x80 [] __mutex_lock_common+0x4d/0x410 [] mutex_lock_nested+0x18/0x20 [] reiserfs_write_lock+0x28/0x40 [reiserfs] [] do_journal_begin_r+0x86/0x340 [reiserfs] [] journal_begin+0x77/0x140 [reiserfs] [] reiserfs_remount+0x224/0x530 [reiserfs] [] do_remount_sb+0x60/0x110 [] do_mount+0x625/0x790 [] sys_mount+0x84/0xb0 [] syscall_call+0x7/0xb -> #0 (&journal->j_mutex){+.+...}: [] __lock_acquire+0x1026/0x1180 [] lock_acquire+0x67/0x80 [] __mutex_lock_common+0x4d/0x410 [] mutex_lock_nested+0x18/0x20 [] do_journal_begin_r+0x7f/0x340 [reiserfs] [] journal_begin+0x77/0x140 [reiserfs] [] reiserfs_persistent_transaction+0x41/0x90 [reiserfs] [] reiserfs_get_block+0x22c/0x1530 [reiserfs] [] __block_prepare_write+0x1bb/0x3a0 [] block_prepare_write+0x26/0x40 [] reiserfs_prepare_write+0x88/0x170 [reiserfs] [] reiserfs_unpack+0xe6/0x120 [reiserfs] [] reiserfs_ioctl+0x272/0x320 [reiserfs] [] vfs_ioctl+0x28/0xa0 [] do_vfs_ioctl+0x32d/0x5c0 [] sys_ioctl+0x63/0x70 [] syscall_call+0x7/0xb other info that might help us debug this: 2 locks held by lilo/1620: #0: (&sb->s_type->i_mutex_key#8){+.+.+.}, at: [] reiserfs_unpack+0x6a/0x120 [reiserfs] #1: (&REISERFS_SB(s)->lock){+.+.+.}, at: [] reiserfs_write_lock+0x28/0x40 [reiserfs] stack backtrace: Pid: 1620, comm: lilo Not tainted 2.6.35.4.4a #3 Call Trace: [] __lock_acquire+0x1026/0x1180 [] lock_acquire+0x67/0x80 [] __mutex_lock_common+0x4d/0x410 [] mutex_lock_nested+0x18/0x20 [] do_journal_begin_r+0x7f/0x340 [reiserfs] [] journal_begin+0x77/0x140 [reiserfs] [] reiserfs_persistent_transaction+0x41/0x90 [reiserfs] [] reiserfs_get_block+0x22c/0x1530 [reiserfs] [] __block_prepare_write+0x1bb/0x3a0 [] block_prepare_write+0x26/0x40 [] reiserfs_prepare_write+0x88/0x170 [reiserfs] [] reiserfs_unpack+0xe6/0x120 [reiserfs] [] reiserfs_ioctl+0x272/0x320 [reiserfs] [] vfs_ioctl+0x28/0xa0 [] do_vfs_ioctl+0x32d/0x5c0 [] sys_ioctl+0x63/0x70 [] syscall_call+0x7/0xb Reported-by: Jarek Poplawski Tested-by: Jarek Poplawski Signed-off-by: Frederic Weisbecker Cc: Jeff Mahoney Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/reiserfs/ioctl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index 679d5029f50f..5cbb81e134ac 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c @@ -170,6 +170,7 @@ int reiserfs_prepare_write(struct file *f, struct page *page, int reiserfs_unpack(struct inode *inode, struct file *filp) { int retval = 0; + int depth; int index; struct page *page; struct address_space *mapping; @@ -189,7 +190,7 @@ int reiserfs_unpack(struct inode *inode, struct file *filp) ** us */ reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb); - reiserfs_write_lock(inode->i_sb); + depth = reiserfs_write_lock_once(inode->i_sb); write_from = inode->i_size & (blocksize - 1); /* if we are on a block boundary, we are already unpacked. */ @@ -224,6 +225,6 @@ int reiserfs_unpack(struct inode *inode, struct file *filp) out: mutex_unlock(&inode->i_mutex); - reiserfs_write_unlock(inode->i_sb); + reiserfs_write_unlock_once(inode->i_sb, depth); return retval; } -- cgit v1.2.3 From f4604440d6512452e75675272364f14af3521af0 Mon Sep 17 00:00:00 2001 From: Joel Becker Date: Wed, 29 Sep 2010 17:33:05 -0700 Subject: ocfs2: Don't walk off the end of fast symlinks. commit 1fc8a117865b54590acd773a55fbac9221b018f0 upstream. ocfs2 fast symlinks are NUL terminated strings stored inline in the inode data area. However, disk corruption or a local attacker could, in theory, remove that NUL. Because we're using strlen() (my fault, introduced in a731d1 when removing vfs_follow_link()), we could walk off the end of that string. Signed-off-by: Joel Becker Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/symlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index 32499d213fc4..9975457c981f 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c @@ -128,7 +128,7 @@ static void *ocfs2_fast_follow_link(struct dentry *dentry, } /* Fast symlinks can't be large */ - len = strlen(target); + len = strnlen(target, ocfs2_fast_symlink_chars(inode->i_sb)); link = kzalloc(len + 1, GFP_NOFS); if (!link) { status = -ENOMEM; -- cgit v1.2.3 From ad2f6a9c0d0f32a05fbd033dfd0c8ac41e635125 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 16 Aug 2010 20:26:51 +0100 Subject: mfd: Ignore non-GPIO IRQs when setting wm831x IRQ types commit c9d66d3515bbb0ad8062721487de7ade02d2b936 upstream. The driver was originally tested with an additional patch which made this unneeded but that patch had issuges and got lost on the way to mainline, causing problems when the errors are reported. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/wm831x-irq.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c index 7dabe4dbd373..294183b6260b 100644 --- a/drivers/mfd/wm831x-irq.c +++ b/drivers/mfd/wm831x-irq.c @@ -394,8 +394,13 @@ static int wm831x_irq_set_type(unsigned int irq, unsigned int type) irq = irq - wm831x->irq_base; - if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) - return -EINVAL; + if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) { + /* Ignore internal-only IRQs */ + if (irq >= 0 && irq < WM831X_NUM_IRQS) + return 0; + else + return -EINVAL; + } switch (type) { case IRQ_TYPE_EDGE_BOTH: -- cgit v1.2.3 From 7ca9783455c1226bcecd1e543b50e6cc38994535 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 17 Sep 2010 00:38:25 +0200 Subject: wext: fix potential private ioctl memory content leak commit df6d02300f7c2fbd0fbe626d819c8e5237d72c62 upstream. When a driver doesn't fill the entire buffer, old heap contents may remain, and if it also doesn't update the length properly, this old heap content will be copied back to userspace. It is very unlikely that this happens in any of the drivers using private ioctls since it would show up as junk being reported by iwpriv, but it seems better to be safe here, so use kzalloc. Reported-by: Jeff Mahoney Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/wireless/wext-priv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/wext-priv.c b/net/wireless/wext-priv.c index 3feb28e41c53..674d426a9d24 100644 --- a/net/wireless/wext-priv.c +++ b/net/wireless/wext-priv.c @@ -152,7 +152,7 @@ static int ioctl_private_iw_point(struct iw_point *iwp, unsigned int cmd, } else if (!iwp->pointer) return -EFAULT; - extra = kmalloc(extra_size, GFP_KERNEL); + extra = kzalloc(extra_size, GFP_KERNEL); if (!extra) return -ENOMEM; -- cgit v1.2.3 From 6c4a46eccf8cb90c312ba93bccccb6857d07df80 Mon Sep 17 00:00:00 2001 From: Luca Tettamanti Date: Wed, 22 Sep 2010 10:41:58 +0000 Subject: atl1: fix resume commit ec5a32f67c603b11d68eb283d94eb89a4f6cfce1 upstream. adapter->cmb.cmb is initialized when the device is opened and freed when it's closed. Accessing it unconditionally during resume results either in a crash (NULL pointer dereference, when the interface has not been opened yet) or data corruption (when the interface has been used and brought down adapter->cmb.cmb points to a deallocated memory area). Signed-off-by: Luca Tettamanti Acked-by: Chris Snook Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/atlx/atl1.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 63b9ba0cc67e..bbd6e3009be0 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -2847,10 +2847,11 @@ static int atl1_resume(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D3cold, 0); atl1_reset_hw(&adapter->hw); - adapter->cmb.cmb->int_stats = 0; - if (netif_running(netdev)) + if (netif_running(netdev)) { + adapter->cmb.cmb->int_stats = 0; atl1_up(adapter); + } netif_device_attach(netdev); return 0; -- cgit v1.2.3 From 75a0ef0b7765f5c98be64f6fbcdceb0693b84210 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 10 Oct 2010 19:52:15 -0700 Subject: x86, numa: For each node, register the memory blocks actually used commit 73cf624d029d776a33d0a80c695485b3f9b36231 upstream. Russ reported SGI UV is broken recently. He said: | The SRAT table shows that memory range is spread over two nodes. | | SRAT: Node 0 PXM 0 100000000-800000000 | SRAT: Node 1 PXM 1 800000000-1000000000 | SRAT: Node 0 PXM 0 1000000000-1080000000 | |Previously, the kernel early_node_map[] would show three entries |with the proper node. | |[ 0.000000] 0: 0x00100000 -> 0x00800000 |[ 0.000000] 1: 0x00800000 -> 0x01000000 |[ 0.000000] 0: 0x01000000 -> 0x01080000 | |The problem is recent community kernel early_node_map[] shows |only two entries with the node 0 entry overlapping the node 1 |entry. | | 0: 0x00100000 -> 0x01080000 | 1: 0x00800000 -> 0x01000000 After looking at the changelog, Found out that it has been broken for a while by following commit |commit 8716273caef7f55f39fe4fc6c69c5f9f197f41f1 |Author: David Rientjes |Date: Fri Sep 25 15:20:04 2009 -0700 | | x86: Export srat physical topology Before that commit, register_active_regions() is called for every SRAT memory entry right away. Use nodememblk_range[] instead of nodes[] in order to make sure we capture the actual memory blocks registered with each node. nodes[] contains an extended range which spans all memory regions associated with a node, but that does not mean that all the memory in between are included. Reported-by: Russ Anderson Tested-by: Russ Anderson Signed-off-by: Yinghai Lu LKML-Reference: <4CB27BDF.5000800@kernel.org> Acked-by: David Rientjes Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/srat_64.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index f9897f7a9ef1..9c0d0d399c30 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c @@ -420,9 +420,11 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) return -1; } - for_each_node_mask(i, nodes_parsed) - e820_register_active_regions(i, nodes[i].start >> PAGE_SHIFT, - nodes[i].end >> PAGE_SHIFT); + for (i = 0; i < num_node_memblks; i++) + e820_register_active_regions(memblk_nodeid[i], + node_memblk_range[i].start >> PAGE_SHIFT, + node_memblk_range[i].end >> PAGE_SHIFT); + /* for out of order entries in SRAT */ sort_node_map(); if (!nodes_cover_memory(nodes)) { -- cgit v1.2.3 From c578c13150d904533c99c2fa7759ff754ca4cee6 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 8 Oct 2010 12:08:34 +0200 Subject: x86, AMD, MCE thresholding: Fix the MCi_MISCj iteration order commit 6dcbfe4f0b4e17e289d56fa534b7ce5a6b7f63a3 upstream. This fixes possible cases of not collecting valid error info in the MCE error thresholding groups on F10h hardware. The current code contains a subtle problem of checking only the Valid bit of MSR0000_0413 (which is MC4_MISC0 - DRAM thresholding group) in its first iteration and breaking out if the bit is cleared. But (!), this MSR contains an offset value, BlkPtr[31:24], which points to the remaining MSRs in this thresholding group which might contain valid information too. But if we bail out only after we checked the valid bit in the first MSR and not the block pointer too, we miss that other information. The thing is, MC4_MISC0[BlkPtr] is not predicated on MCi_STATUS[MiscV] or MC4_MISC0[Valid] and should be checked prior to iterating over the MCI_MISCj thresholding group, irrespective of the MC4_MISC0[Valid] setting. Signed-off-by: Borislav Petkov Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mcheck/mce_amd.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 224392d8fe8c..f80ff85d1ef9 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -141,6 +141,7 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) address = (low & MASK_BLKPTR_LO) >> 21; if (!address) break; + address += MCG_XBLK_ADDR; } else ++address; @@ -148,12 +149,8 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) if (rdmsr_safe(address, &low, &high)) break; - if (!(high & MASK_VALID_HI)) { - if (block) - continue; - else - break; - } + if (!(high & MASK_VALID_HI)) + continue; if (!(high & MASK_CNTP_HI) || (high & MASK_LOCKED_HI)) -- cgit v1.2.3 From fe17f612b3ea86e7af439432fc6b7d6d5e15d508 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 15 Oct 2010 11:09:28 -0700 Subject: De-pessimize rds_page_copy_user commit 799c10559d60f159ab2232203f222f18fa3c4a5f upstream. Don't try to "optimize" rds_page_copy_user() by using kmap_atomic() and the unsafe atomic user mode accessor functions. It's actually slower than the straightforward code on any reasonable modern CPU. Back when the code was written (although probably not by the time it was actually merged, though), 32-bit x86 may have been the dominant architecture. And there kmap_atomic() can be a lot faster than kmap() (unless you have very good locality, in which case the virtual address caching by kmap() can overcome all the downsides). But these days, x86-64 may not be more populous, but it's getting there (and if you care about performance, it's definitely already there - you'd have upgraded your CPU's already in the last few years). And on x86-64, the non-kmap_atomic() version is faster, simply because the code is simpler and doesn't have the "re-try page fault" case. People with old hardware are not likely to care about RDS anyway, and the optimization for the 32-bit case is simply buggy, since it doesn't verify the user addresses properly. Reported-by: Dan Rosenberg Acked-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- net/rds/page.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/net/rds/page.c b/net/rds/page.c index 595a952d4b17..1dfbfea12e9b 100644 --- a/net/rds/page.c +++ b/net/rds/page.c @@ -57,30 +57,17 @@ int rds_page_copy_user(struct page *page, unsigned long offset, unsigned long ret; void *addr; - if (to_user) + addr = kmap(page); + if (to_user) { rds_stats_add(s_copy_to_user, bytes); - else + ret = copy_to_user(ptr, addr + offset, bytes); + } else { rds_stats_add(s_copy_from_user, bytes); - - addr = kmap_atomic(page, KM_USER0); - if (to_user) - ret = __copy_to_user_inatomic(ptr, addr + offset, bytes); - else - ret = __copy_from_user_inatomic(addr + offset, ptr, bytes); - kunmap_atomic(addr, KM_USER0); - - if (ret) { - addr = kmap(page); - if (to_user) - ret = copy_to_user(ptr, addr + offset, bytes); - else - ret = copy_from_user(addr + offset, ptr, bytes); - kunmap(page); - if (ret) - return -EFAULT; + ret = copy_from_user(addr + offset, ptr, bytes); } + kunmap(page); - return 0; + return ret ? -EFAULT : 0; } EXPORT_SYMBOL_GPL(rds_page_copy_user); -- cgit v1.2.3 From 14d7e74a7f658fdd370e9a790b55e3b93eb259fc Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 17 Oct 2010 14:09:12 +0200 Subject: firewire: ohci: fix TI TSB82AA2 regression since 2.6.35 commit aa0170fff3c26bf2b42159af2dd9cf86444c292a upstream. Revert commit 54672386ccf36ffa21d1de8e75624af83f9b0eeb "firewire: ohci: fix up configuration of TI chips". It caused massive slow-down and data corruption with a TSB82AA2 based StarTech EC1394B2 ExpressCard and FireWire 800 harddisks. https://bugs.launchpad.net/ubuntu/+source/linux/+bug/657081 http://thread.gmane.org/gmane.linux.kernel.firewire.user/4013 The fact that some card EEPROMs do not program these enhancements may be related to TSB81BA3 phy chip errata, if not to bugs of TSB82AA2 itself. We could re-add these configuration steps, but only conditional on a whitelist of cards on which these enhancements bring a proven positive effect. Reported-and-tested-by: Eric Shattow Cc: Clemens Ladisch Signed-off-by: Stefan Richter Signed-off-by: Greg Kroah-Hartman --- drivers/firewire/ohci.c | 19 +------------------ drivers/firewire/ohci.h | 8 -------- 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 9f627e758cfc..4b521dd5a9d9 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2439,7 +2439,7 @@ static int __devinit pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) { struct fw_ohci *ohci; - u32 bus_options, max_receive, link_speed, version, link_enh; + u32 bus_options, max_receive, link_speed, version; u64 guid; int i, err, n_ir, n_it; size_t size; @@ -2492,23 +2492,6 @@ static int __devinit pci_probe(struct pci_dev *dev, if (param_quirks) ohci->quirks = param_quirks; - /* TI OHCI-Lynx and compatible: set recommended configuration bits. */ - if (dev->vendor == PCI_VENDOR_ID_TI) { - pci_read_config_dword(dev, PCI_CFG_TI_LinkEnh, &link_enh); - - /* adjust latency of ATx FIFO: use 1.7 KB threshold */ - link_enh &= ~TI_LinkEnh_atx_thresh_mask; - link_enh |= TI_LinkEnh_atx_thresh_1_7K; - - /* use priority arbitration for asynchronous responses */ - link_enh |= TI_LinkEnh_enab_unfair; - - /* required for aPhyEnhanceEnable to work */ - link_enh |= TI_LinkEnh_enab_accel; - - pci_write_config_dword(dev, PCI_CFG_TI_LinkEnh, link_enh); - } - ar_context_init(&ohci->ar_request_ctx, ohci, OHCI1394_AsReqRcvContextControlSet); diff --git a/drivers/firewire/ohci.h b/drivers/firewire/ohci.h index 3bc9a5d744eb..d49e1469a986 100644 --- a/drivers/firewire/ohci.h +++ b/drivers/firewire/ohci.h @@ -154,12 +154,4 @@ #define OHCI1394_phy_tcode 0xe -/* TI extensions */ - -#define PCI_CFG_TI_LinkEnh 0xf4 -#define TI_LinkEnh_enab_accel 0x00000002 -#define TI_LinkEnh_enab_unfair 0x00000080 -#define TI_LinkEnh_atx_thresh_mask 0x00003000 -#define TI_LinkEnh_atx_thresh_1_7K 0x00001000 - #endif /* _FIREWIRE_OHCI_H */ -- cgit v1.2.3 From f7352937752cdf338158a320b37e99b7189b411a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 8 Oct 2010 13:40:27 +0100 Subject: drm/i915: Prevent module unload to avoid random memory corruption commit 6939a5aca7cfada279a24c307e772f33104fca20 upstream. The i915 driver has quite a few module unload bugs, the known ones at least have fixes that are targeting 2.6.37. However, in order to maintain a stable kernel, we should prevent this known random memory corruption following driver unload. This should have very low impact on normal users who are unlikely to need to unload the i915 driver. Suggested-by: Thomas Gleixner Acked-by: Daniel Vetter Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_dma.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index ce8ff0e55152..f9a1437919da 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -2222,6 +2222,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev_priv->mchdev_lock = &mchdev_lock; spin_unlock(&mchdev_lock); + /* XXX Prevent module unload due to memory corruption bugs. */ + __module_get(THIS_MODULE); + return 0; out_workqueue_free: -- cgit v1.2.3 From 264cf4e651212e9f38cb24399c3cf513e13adcd2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 26 Sep 2010 20:50:05 +0100 Subject: drm/i915: Sanity check pread/pwrite commit ce9d419dbecc292cc3e06e8b1d6d123d3fa813a4 upstream. Move the access control up from the fast paths, which are no longer universally taken first, up into the caller. This then duplicates some sanity checking along the slow paths, but is much simpler. Tracked as CVE-2010-2962. Reported-by: Kees Cook Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_gem.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9dc220f2e4dd..50e6984f3572 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -465,8 +465,15 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, */ if (args->offset > obj->size || args->size > obj->size || args->offset + args->size > obj->size) { - drm_gem_object_unreference_unlocked(obj); - return -EINVAL; + ret = -EINVAL; + goto err; + } + + if (!access_ok(VERIFY_WRITE, + (char __user *)(uintptr_t)args->data_ptr, + args->size)) { + ret = -EFAULT; + goto err; } if (i915_gem_object_needs_bit17_swizzle(obj)) { @@ -478,8 +485,8 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, file_priv); } +err: drm_gem_object_unreference_unlocked(obj); - return ret; } @@ -568,8 +575,6 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, user_data = (char __user *) (uintptr_t) args->data_ptr; remain = args->size; - if (!access_ok(VERIFY_READ, user_data, remain)) - return -EFAULT; mutex_lock(&dev->struct_mutex); @@ -928,8 +933,15 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, */ if (args->offset > obj->size || args->size > obj->size || args->offset + args->size > obj->size) { - drm_gem_object_unreference_unlocked(obj); - return -EINVAL; + ret = -EINVAL; + goto err; + } + + if (!access_ok(VERIFY_READ, + (char __user *)(uintptr_t)args->data_ptr, + args->size)) { + ret = -EFAULT; + goto err; } /* We can only do the GTT pwrite on untiled buffers, as otherwise @@ -963,8 +975,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, DRM_INFO("pwrite failed %d\n", ret); #endif +err: drm_gem_object_unreference_unlocked(obj); - return ret; } -- cgit v1.2.3 From 39a3fcd46e669818b54dd9f587f11a40ccdbebe2 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 27 Sep 2010 10:35:44 -0700 Subject: drm/i915: fix GMCH power reporting commit d270ae34eb77c58dea60e5b1e300a698d2ce39ac upstream. The IPS driver needs to know the current power consumption of the GMCH in order to make decisions about when to increase or decrease the CPU and/or GPU power envelope. So fix up the divisions to save the results so the numbers are actually correct (contrary to some earlier comments and code, these functions do not modify the first argument and use it for the result). Signed-off-by: Jesse Barnes Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_dma.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index f9a1437919da..d396fe5915dd 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1778,9 +1778,9 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv) } } - div_u64(diff, diff1); + diff = div_u64(diff, diff1); ret = ((m * diff) + c); - div_u64(ret, 10); + ret = div_u64(ret, 10); dev_priv->last_count1 = total_count; dev_priv->last_time1 = now; @@ -1849,7 +1849,7 @@ void i915_update_gfx_val(struct drm_i915_private *dev_priv) /* More magic constants... */ diff = diff * 1181; - div_u64(diff, diffms * 10); + diff = div_u64(diff, diffms * 10); dev_priv->gfx_power = diff; } -- cgit v1.2.3 From ac9f371955a1d6ce27b1464a86137b4cdb0f43d8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 27 Sep 2010 21:28:30 +0100 Subject: drm: Prune GEM vma entries commit 31dfbc93923c0aaa0440b809f80ff2830c6a531a upstream. Hook the GEM vm open/close ops into the generic drm vm open/close so that the private vma entries are created and destroy appropriately. Fixes the leak of the drm_vma_entries during the lifetime of the filp. Reported-by: Matt Mackall Cc: Jesse Barnes Signed-off-by: Chris Wilson Acked-by: Jesse Barnes Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_gem.c | 9 ++++++++- drivers/gpu/drm/drm_vm.c | 28 ++++++++++++++++++---------- include/drm/drmP.h | 1 + 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 33dad3fa6043..d9a56e01d53b 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -517,6 +517,10 @@ void drm_gem_vm_open(struct vm_area_struct *vma) struct drm_gem_object *obj = vma->vm_private_data; drm_gem_object_reference(obj); + + mutex_lock(&obj->dev->struct_mutex); + drm_vm_open_locked(vma); + mutex_unlock(&obj->dev->struct_mutex); } EXPORT_SYMBOL(drm_gem_vm_open); @@ -524,7 +528,10 @@ void drm_gem_vm_close(struct vm_area_struct *vma) { struct drm_gem_object *obj = vma->vm_private_data; - drm_gem_object_unreference_unlocked(obj); + mutex_lock(&obj->dev->struct_mutex); + drm_vm_close_locked(vma); + drm_gem_object_unreference(obj); + mutex_unlock(&obj->dev->struct_mutex); } EXPORT_SYMBOL(drm_gem_vm_close); diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index c3b13fb41d0c..3813e844d74f 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c @@ -433,15 +433,7 @@ static void drm_vm_open(struct vm_area_struct *vma) mutex_unlock(&dev->struct_mutex); } -/** - * \c close method for all virtual memory types. - * - * \param vma virtual memory area. - * - * Search the \p vma private data entry in drm_device::vmalist, unlink it, and - * free it. - */ -static void drm_vm_close(struct vm_area_struct *vma) +void drm_vm_close_locked(struct vm_area_struct *vma) { struct drm_file *priv = vma->vm_file->private_data; struct drm_device *dev = priv->minor->dev; @@ -451,7 +443,6 @@ static void drm_vm_close(struct vm_area_struct *vma) vma->vm_start, vma->vm_end - vma->vm_start); atomic_dec(&dev->vma_count); - mutex_lock(&dev->struct_mutex); list_for_each_entry_safe(pt, temp, &dev->vmalist, head) { if (pt->vma == vma) { list_del(&pt->head); @@ -459,6 +450,23 @@ static void drm_vm_close(struct vm_area_struct *vma) break; } } +} + +/** + * \c close method for all virtual memory types. + * + * \param vma virtual memory area. + * + * Search the \p vma private data entry in drm_device::vmalist, unlink it, and + * free it. + */ +static void drm_vm_close(struct vm_area_struct *vma) +{ + struct drm_file *priv = vma->vm_file->private_data; + struct drm_device *dev = priv->minor->dev; + + mutex_lock(&dev->struct_mutex); + drm_vm_close_locked(vma); mutex_unlock(&dev->struct_mutex); } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index c1b987158dfa..1bebb043776a 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1149,6 +1149,7 @@ extern int drm_release(struct inode *inode, struct file *filp); extern int drm_mmap(struct file *filp, struct vm_area_struct *vma); extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma); extern void drm_vm_open_locked(struct vm_area_struct *vma); +extern void drm_vm_close_locked(struct vm_area_struct *vma); extern resource_size_t drm_core_get_map_ofs(struct drm_local_map * map); extern resource_size_t drm_core_get_reg_ofs(struct drm_device *dev); extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); -- cgit v1.2.3 From 9b909fc8c3e8e04d012c20f38de2d57aedfc16a0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 30 Sep 2010 09:10:26 +0100 Subject: drm: Hold the mutex when dropping the last GEM reference (v2) commit 39b4d07aa3583ceefe73622841303a0a3e942ca1 upstream. In order to be fully threadsafe we need to check that the drm_gem_object refcount is still 0 after acquiring the mutex in order to call the free function. Otherwise, we may encounter scenarios like: Thread A: Thread B: drm_gem_close unreference_unlocked kref_put mutex_lock ... i915_gem_evict ... kref_get -> BUG ... i915_gem_unbind ... kref_put ... i915_gem_object_free ... mutex_unlock mutex_lock i915_gem_object_free -> BUG i915_gem_object_unbind kfree mutex_unlock Note that no driver is currently using the free_unlocked vfunc and it is scheduled for removal, hasten that process. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=30454 Reported-and-Tested-by: Magnus Kessler Signed-off-by: Chris Wilson Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_gem.c | 22 ---------------------- include/drm/drmP.h | 10 ++++++---- 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index d9a56e01d53b..f353cdfbf147 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -451,28 +451,6 @@ drm_gem_object_free(struct kref *kref) } EXPORT_SYMBOL(drm_gem_object_free); -/** - * Called after the last reference to the object has been lost. - * Must be called without holding struct_mutex - * - * Frees the object - */ -void -drm_gem_object_free_unlocked(struct kref *kref) -{ - struct drm_gem_object *obj = (struct drm_gem_object *) kref; - struct drm_device *dev = obj->dev; - - if (dev->driver->gem_free_object_unlocked != NULL) - dev->driver->gem_free_object_unlocked(obj); - else if (dev->driver->gem_free_object != NULL) { - mutex_lock(&dev->struct_mutex); - dev->driver->gem_free_object(obj); - mutex_unlock(&dev->struct_mutex); - } -} -EXPORT_SYMBOL(drm_gem_object_free_unlocked); - static void drm_gem_object_ref_bug(struct kref *list_kref) { BUG(); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 1bebb043776a..7c9d28d635b5 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -802,7 +802,6 @@ struct drm_driver { */ int (*gem_init_object) (struct drm_gem_object *obj); void (*gem_free_object) (struct drm_gem_object *obj); - void (*gem_free_object_unlocked) (struct drm_gem_object *obj); /* vga arb irq handler */ void (*vgaarb_irq)(struct drm_device *dev, bool state); @@ -1431,7 +1430,6 @@ int drm_gem_init(struct drm_device *dev); void drm_gem_destroy(struct drm_device *dev); void drm_gem_object_release(struct drm_gem_object *obj); void drm_gem_object_free(struct kref *kref); -void drm_gem_object_free_unlocked(struct kref *kref); struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev, size_t size); int drm_gem_object_init(struct drm_device *dev, @@ -1457,8 +1455,12 @@ drm_gem_object_unreference(struct drm_gem_object *obj) static inline void drm_gem_object_unreference_unlocked(struct drm_gem_object *obj) { - if (obj != NULL) - kref_put(&obj->refcount, drm_gem_object_free_unlocked); + if (obj != NULL) { + struct drm_device *dev = obj->dev; + mutex_lock(&dev->struct_mutex); + kref_put(&obj->refcount, drm_gem_object_free); + mutex_unlock(&dev->struct_mutex); + } } int drm_gem_handle_create(struct drm_file *file_priv, -- cgit v1.2.3 From 64ea843fbb13bb9d3014751a114f069461b32da3 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 25 Sep 2010 17:45:50 +1000 Subject: drm/radeon: fix PCI ID 5657 to be an RV410 commit f459ffbdfd04edb4a8ce6eea33170eb057a5e695 upstream. fixes https://bugzilla.kernel.org/show_bug.cgi?id=19012 Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- include/drm/drm_pciids.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 3a9940ef728b..883c1d439899 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -85,7 +85,6 @@ {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \ {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \ {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \ - {0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \ {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \ {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \ {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \ @@ -103,6 +102,7 @@ {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \ {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \ {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ {0x1002, 0x5954, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \ -- cgit v1.2.3 From 86e3fc7194c037faae3f3094563f75312d3512a0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 12 Oct 2010 12:20:31 -0400 Subject: drm/radeon/kms: fix possible sigbus in evergreen accel code Not upstream in Linus's tree as it was fixed by a much more intrusive patch in a different manner, commit c919b371cb734f42b11 2.6.35 and 2.6.36 do not contain blit support for evergreen asics so if they use unmappable vram, you can end up with an unreachable buffer address. This should not be applied to drm-next as that tree already contains evergreen blit support. This should only be applied to the 2.6.35 and 2.6.36 stable trees. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=30188 Signed-off-by: Alex Deucher Acked-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 0bfb83638a5d..82cc369a85ec 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1389,6 +1389,8 @@ int evergreen_mc_init(struct radeon_device *rdev) rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; rdev->mc.visible_vram_size = rdev->mc.aper_size; + /* limit it to the aperture size for now as there is no blit support in 2.6.35/36*/ + rdev->mc.real_vram_size = rdev->mc.visible_vram_size; r600_vram_gtt_location(rdev, &rdev->mc); radeon_update_bandwidth_info(rdev); -- cgit v1.2.3 From f68f4a26c5390ce47f6b4ffefb1bf35e7cac93be Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 24 Sep 2010 14:59:32 -0400 Subject: drm/radeon/kms: fix up encoder info messages for DFP6 commit 73758a5d51280ca0613b8380fc07351f4d64f9c8 upstream. encoder info was not printed properly on boards using the DFP6 id. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 8154cdf796e4..2d95376c3ddf 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -349,6 +349,8 @@ static void radeon_print_display_setup(struct drm_device *dev) DRM_INFO(" DFP4: %s\n", encoder_names[radeon_encoder->encoder_id]); if (devices & ATOM_DEVICE_DFP5_SUPPORT) DRM_INFO(" DFP5: %s\n", encoder_names[radeon_encoder->encoder_id]); + if (devices & ATOM_DEVICE_DFP6_SUPPORT) + DRM_INFO(" DFP6: %s\n", encoder_names[radeon_encoder->encoder_id]); if (devices & ATOM_DEVICE_TV1_SUPPORT) DRM_INFO(" TV1: %s\n", encoder_names[radeon_encoder->encoder_id]); if (devices & ATOM_DEVICE_CV_SUPPORT) -- cgit v1.2.3 From 0097ad30cacd143b61ae58f0e9830ae8be3c6c79 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 27 Sep 2010 10:57:10 -0400 Subject: drm/radeon/kms: fix potential segfault in r600_ioctl_wait_idle commit e488459a0e131acc9e14df093cfee740bc431953 upstream. radeon_gem_wait_idle_ioctl can apparently get called prior to the vram page being set up or even if accel if false, so make sure it's valid before using it. Should fix: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=597636 https://bugs.freedesktop.org/show_bug.cgi?id=29834 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/r600.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 952cc780230f..eddeff34e73a 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3522,7 +3522,8 @@ void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo) /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL */ - if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) { + if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) && + rdev->vram_scratch.ptr) { void __iomem *ptr = (void *)rdev->vram_scratch.ptr; u32 tmp; -- cgit v1.2.3 From 414c9c2726f9aa72ee37c64e24960a6a81374c34 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 27 Sep 2010 11:33:00 -0400 Subject: drm/radeon/kms: add quirk for MSI K9A2GM motherboard commit f36fce0f49ed40f3e843d45fa53d476d63444b58 upstream. Board has no digital connectors Reported-by: Andy Walls Tested-by: Andy Walls Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_atombios.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 6bfef51bd583..d7c18e5233e5 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -226,6 +226,15 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, *connector_type = DRM_MODE_CONNECTOR_DVID; } + /* MSI K9A2GM V2/V3 board has no HDMI or DVI */ + if ((dev->pdev->device == 0x796e) && + (dev->pdev->subsystem_vendor == 0x1462) && + (dev->pdev->subsystem_device == 0x7302)) { + if ((supported_device == ATOM_DEVICE_DFP2_SUPPORT) || + (supported_device == ATOM_DEVICE_DFP3_SUPPORT)) + return false; + } + /* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */ if ((dev->pdev->device == 0x7941) && (dev->pdev->subsystem_vendor == 0x147b) && -- cgit v1.2.3 From 63cb57e4d31311bf80639d07ba006d39651304bb Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Wed, 13 Oct 2010 09:31:56 +0200 Subject: mmc: sdio: fix SDIO suspend/resume regression commit 1c8cf9c997a4a6b36e907c7ede5f048aeaab1644 upstream. Fix SDIO suspend/resume regression introduced by 4c2ef25fe0b "mmc: fix all hangs related to mmc/sd card insert/removal during suspend/resume": PM: Syncing filesystems ... done. Freezing user space processes ... (elapsed 0.01 seconds) done. Freezing remaining freezable tasks ... (elapsed 0.01 seconds) done. Suspending console(s) (use no_console_suspend to debug) pm_op(): platform_pm_suspend+0x0/0x5c returns -38 PM: Device pxa2xx-mci.0 failed to suspend: error -38 PM: Some devices failed to suspend 4c2ef25fe0b moved the card removal/insertion mechanism out of MMC's suspend/resume path and into pm notifiers (mmc_pm_notify), and that broke SDIO's expectation that mmc_suspend_host() will remove the card, and squash the error, in case -ENOSYS is returned from the bus suspend handler (mmc_sdio_suspend() in this case). mmc_sdio_suspend() is using this whenever at least one of the card's SDIO function drivers does not have suspend/resume handlers - in that case it is agreed to force removal of the entire card. This patch fixes this regression by trivially bringing back that part of mmc_suspend_host(), which was removed by 4c2ef25fe0b. Reported-and-tested-by: Sven Neumann Signed-off-by: Ohad Ben-Cohen Cc: Maxim Levitsky Acked-by: Nicolas Pitre Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/core/core.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 83e7543b55d9..2876c3d80284 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1277,6 +1277,19 @@ int mmc_suspend_host(struct mmc_host *host) if (host->bus_ops && !host->bus_dead) { if (host->bus_ops->suspend) err = host->bus_ops->suspend(host); + if (err == -ENOSYS || !host->bus_ops->resume) { + /* + * We simply "remove" the card in this case. + * It will be redetected on resume. + */ + if (host->bus_ops->remove) + host->bus_ops->remove(host); + mmc_claim_host(host); + mmc_detach_bus(host); + mmc_release_host(host); + host->pm_flags = 0; + err = 0; + } } mmc_bus_put(host); -- cgit v1.2.3 From 47f4633f95e4ecafd829f4cfcb18d746d1afc5cd Mon Sep 17 00:00:00 2001 From: Olivier Grenie Date: Tue, 7 Sep 2010 12:50:45 -0300 Subject: V4L/DVB: dib7770: enable the current mirror commit 90e12cec707204930934acdb5efce5f94a163a5f upstream. To improve performance on DiB7770-devices enabling the current mirror is needed. This patch adds an option to the dib7000p-driver to do that and it creates a separate device-entry in dib0700-device to use those changes on hardware which is using the DiB7770. Signed-off-by: Olivier Grenie Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 53 ++++++++++++++++++++++++++++- drivers/media/dvb/frontends/dib7000p.c | 2 ++ drivers/media/dvb/frontends/dib7000p.h | 3 ++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 89c0627908c9..33af683aea5d 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1240,6 +1240,57 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap) return adap->fe == NULL ? -ENODEV : 0; } +/* STK7770P */ +static struct dib7000p_config dib7770p_dib7000p_config = { + .output_mpeg2_in_188_bytes = 1, + + .agc_config_count = 1, + .agc = &dib7070_agc_config, + .bw = &dib7070_bw_config_12_mhz, + .tuner_is_baseband = 1, + .spur_protect = 1, + + .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, + .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, + .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, + + .hostbus_diversity = 1, + .enable_current_mirror = 1, +}; + +static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct usb_device_descriptor *p = &adap->dev->udev->descriptor; + if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) && + p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E)) + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); + else + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); + msleep(10); + dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); + + dib0700_ctrl_clock(adap->dev, 72, 1); + + msleep(10); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); + msleep(10); + dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); + + if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, + &dib7770p_dib7000p_config) != 0) { + err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", + __func__); + return -ENODEV; + } + + adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, + &dib7770p_dib7000p_config); + return adap->fe == NULL ? -ENODEV : 0; +} + /* DIB807x generic */ static struct dibx000_agc_config dib807x_agc_config[2] = { { @@ -2592,7 +2643,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { .pid_filter_count = 32, .pid_filter = stk70x0p_pid_filter, .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, - .frontend_attach = stk7070p_frontend_attach, + .frontend_attach = stk7770p_frontend_attach, .tuner_attach = dib7770p_tuner_attach, DIB0700_DEFAULT_STREAMING_CONFIG(0x02), diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index 2e28b973dfd3..73f59ab06c86 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -260,6 +260,8 @@ static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_ad // dprintk( "908: %x, 909: %x\n", reg_908, reg_909); + reg_908 |= (state->cfg.enable_current_mirror & 1) << 7; + dib7000p_write_word(state, 908, reg_908); dib7000p_write_word(state, 909, reg_909); } diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h index 805dd13a97ee..04a744938cca 100644 --- a/drivers/media/dvb/frontends/dib7000p.h +++ b/drivers/media/dvb/frontends/dib7000p.h @@ -33,6 +33,9 @@ struct dib7000p_config { int (*agc_control) (struct dvb_frontend *, u8 before); u8 output_mode; + + u8 enable_current_mirror : 1; + }; #define DEFAULT_DIB7000P_I2C_ADDRESS 18 -- cgit v1.2.3 From 4d4e307ad05e8ba402c385d780e2c03ea3c7c495 Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Fri, 1 Oct 2010 07:43:54 +0000 Subject: xfs: properly account for reclaimed inodes commit 081003fff467ea0e727f66d5d435b4f473a789b3 upstream. When marking an inode reclaimable, a per-AG counter is increased, the inode is tagged reclaimable in its per-AG tree, and, when this is the first reclaimable inode in the AG, the AG entry in the per-mount tree is also tagged. When an inode is finally reclaimed, however, it is only deleted from the per-AG tree. Neither the counter is decreased, nor is the parent tree's AG entry untagged properly. Since the tags in the per-mount tree are not cleared, the inode shrinker iterates over all AGs that have had reclaimable inodes at one point in time. The counters on the other hand signal an increasing amount of slab objects to reclaim. Since "70e60ce xfs: convert inode shrinker to per-filesystem context" this is not a real issue anymore because the shrinker bails out after one iteration. But the problem was observable on a machine running v2.6.34, where the reclaimable work increased and each process going into direct reclaim eventually got stuck on the xfs inode shrinking path, trying to scan several million objects. Fix this by properly unwinding the reclaimable-state tracking of an inode when it is reclaimed. Signed-off-by: Johannes Weiner Reviewed-by: Dave Chinner Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- fs/xfs/linux-2.6/xfs_sync.c | 16 ++++++++++++---- fs/xfs/linux-2.6/xfs_sync.h | 1 + fs/xfs/xfs_iget.c | 1 + 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index a51a07c3a70c..f38037d83846 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c @@ -711,13 +711,10 @@ xfs_inode_set_reclaim_tag( } void -__xfs_inode_clear_reclaim_tag( - xfs_mount_t *mp, +__xfs_inode_clear_reclaim( xfs_perag_t *pag, xfs_inode_t *ip) { - radix_tree_tag_clear(&pag->pag_ici_root, - XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); pag->pag_ici_reclaimable--; if (!pag->pag_ici_reclaimable) { /* clear the reclaim tag from the perag radix tree */ @@ -731,6 +728,17 @@ __xfs_inode_clear_reclaim_tag( } } +void +__xfs_inode_clear_reclaim_tag( + xfs_mount_t *mp, + xfs_perag_t *pag, + xfs_inode_t *ip) +{ + radix_tree_tag_clear(&pag->pag_ici_root, + XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); + __xfs_inode_clear_reclaim(pag, ip); +} + /* * Inodes in different states need to be treated differently, and the return * value of xfs_iflush is not sufficient to get this right. The following table diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h index e28139aaa4aa..e4f7e1f2ab0f 100644 --- a/fs/xfs/linux-2.6/xfs_sync.h +++ b/fs/xfs/linux-2.6/xfs_sync.h @@ -47,6 +47,7 @@ int xfs_reclaim_inodes(struct xfs_mount *mp, int mode); void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip); +void __xfs_inode_clear_reclaim(struct xfs_perag *pag, struct xfs_inode *ip); void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, struct xfs_perag *pag, struct xfs_inode *ip); diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 8f8b91be2c99..a8bb8c2d48cb 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -492,6 +492,7 @@ xfs_ireclaim( write_lock(&pag->pag_ici_lock); if (!radix_tree_delete(&pag->pag_ici_root, agino)) ASSERT(0); + __xfs_inode_clear_reclaim(pag, ip); write_unlock(&pag->pag_ici_lock); xfs_perag_put(pag); -- cgit v1.2.3 From 2af177aa5f4de44ac9f142f6bc51469f915ab159 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 5 Oct 2010 15:11:40 -0700 Subject: skge: add quirk to limit DMA commit 392bd0cb000d4aac9e88e4f50823db85e7220688 upstream. Skge devices installed on some Gigabyte motherboards are not able to perform 64 dma correctly due to board PCI implementation, so limit DMA to 32bit if such boards are detected. Bug was reported here: https://bugzilla.redhat.com/show_bug.cgi?id=447489 Signed-off-by: Stanislaw Gruszka Tested-by: Luya Tshimbalanga Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/skge.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 40e5c46e7571..465ae7e84507 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include "skge.h" @@ -3868,6 +3869,8 @@ static void __devinit skge_show_addr(struct net_device *dev) netif_info(skge, probe, skge->netdev, "addr %pM\n", dev->dev_addr); } +static int only_32bit_dma; + static int __devinit skge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -3889,7 +3892,7 @@ static int __devinit skge_probe(struct pci_dev *pdev, pci_set_master(pdev); - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { + if (!only_32bit_dma && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { using_dac = 1; err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); } else if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { @@ -4147,8 +4150,21 @@ static struct pci_driver skge_driver = { .shutdown = skge_shutdown, }; +static struct dmi_system_id skge_32bit_dma_boards[] = { + { + .ident = "Gigabyte nForce boards", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co"), + DMI_MATCH(DMI_BOARD_NAME, "nForce"), + }, + }, + {} +}; + static int __init skge_init_module(void) { + if (dmi_check_system(skge_32bit_dma_boards)) + only_32bit_dma = 1; skge_debug_init(); return pci_register_driver(&skge_driver); } -- cgit v1.2.3 From 431e8d4b696f8cc10db1458865262139dda15e42 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 8 Oct 2010 04:25:00 +0000 Subject: r8169: allocate with GFP_KERNEL flag when able to sleep commit aeb19f6052b5e5c8a24aa444fbff73b84341beac upstream. We have fedora bug report where driver fail to initialize after suspend/resume because of memory allocation errors: https://bugzilla.redhat.com/show_bug.cgi?id=629158 To fix use GFP_KERNEL allocation where possible. Tested-by: Neal Becker Signed-off-by: Stanislaw Gruszka Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/r8169.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index cdc6a5c2e70d..ad9833b2ee79 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -4008,7 +4008,7 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct net_device *dev, struct RxDesc *desc, int rx_buf_sz, - unsigned int align) + unsigned int align, gfp_t gfp) { struct sk_buff *skb; dma_addr_t mapping; @@ -4016,7 +4016,7 @@ static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, pad = align ? align : NET_IP_ALIGN; - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); + skb = __netdev_alloc_skb(dev, rx_buf_sz + pad, gfp); if (!skb) goto err_out; @@ -4047,7 +4047,7 @@ static void rtl8169_rx_clear(struct rtl8169_private *tp) } static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) + u32 start, u32 end, gfp_t gfp) { u32 cur; @@ -4062,7 +4062,7 @@ static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); + tp->rx_buf_sz, tp->align, gfp); if (!skb) break; @@ -4090,7 +4090,7 @@ static int rtl8169_init_ring(struct net_device *dev) memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) + if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC, GFP_KERNEL) != NUM_RX_DESC) goto err_out; rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); @@ -4591,7 +4591,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, count = cur_rx - tp->cur_rx; tp->cur_rx = cur_rx; - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); + delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx, GFP_ATOMIC); if (!delta && count) netif_info(tp, intr, dev, "no Rx buffer allocated\n"); tp->dirty_rx += delta; -- cgit v1.2.3 From 668f36c4044b6541ea4ce92515e89f290a1c979d Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Thu, 14 Oct 2010 13:49:55 -0300 Subject: KVM: i8259: fix migration commit eebb5f31b8d9a2620dcf32297096f8ce1240b179 upstream. Top of kvm_kpic_state structure should have the same memory layout as kvm_pic_state since it is copied by memcpy. Signed-off-by: Gleb Natapov Signed-off-by: Avi Kivity Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/irq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h index cd1f362f413d..4227b1aed869 100644 --- a/arch/x86/kvm/irq.h +++ b/arch/x86/kvm/irq.h @@ -45,7 +45,6 @@ struct kvm_kpic_state { u8 irr; /* interrupt request register */ u8 imr; /* interrupt mask register */ u8 isr; /* interrupt service register */ - u8 isr_ack; /* interrupt ack detection */ u8 priority_add; /* highest irq priority */ u8 irq_base; u8 read_reg_select; @@ -58,6 +57,7 @@ struct kvm_kpic_state { u8 init4; /* true if 4 byte init */ u8 elcr; /* PIIX edge/trigger selection */ u8 elcr_mask; + u8 isr_ack; /* interrupt ack detection */ struct kvm_pic *pics_state; }; -- cgit v1.2.3 From 912ecf4173cb78c209090e43a0e6cd0ca295f1f8 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Thu, 14 Oct 2010 13:49:56 -0300 Subject: KVM: x86: Fix SVM VMCB reset commit 58877679fd393d3ef71aa383031ac7817561463d upstream. On reset, VMCB TSC should be set to zero. Instead, code was setting tsc_offset to zero, which passes through the underlying TSC. Signed-off-by: Zachary Amsden Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/svm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index ce438e0fdd26..5fb0ebd213bf 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -766,7 +766,7 @@ static void init_vmcb(struct vcpu_svm *svm) control->iopm_base_pa = iopm_base; control->msrpm_base_pa = __pa(svm->msrpm); - control->tsc_offset = 0; + control->tsc_offset = 0-native_read_tsc(); control->int_ctl = V_INTR_MASKING_MASK; init_seg(&save->es); -- cgit v1.2.3 From d25faf3214b1991531f2ef64b864751b002fcf8f Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Thu, 14 Oct 2010 13:49:57 -0300 Subject: KVM: x86: Move TSC reset out of vmcb_init commit 47008cd887c1836bcadda123ba73e1863de7a6c4 upstream. The VMCB is reset whenever we receive a startup IPI, so Linux is setting TSC back to zero happens very late in the boot process and destabilizing the TSC. Instead, just set TSC to zero once at VCPU creation time. Why the separate patch? So git-bisect is your friend. Signed-off-by: Zachary Amsden Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/svm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 5fb0ebd213bf..93730fe9f7e9 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -766,7 +766,6 @@ static void init_vmcb(struct vcpu_svm *svm) control->iopm_base_pa = iopm_base; control->msrpm_base_pa = __pa(svm->msrpm); - control->tsc_offset = 0-native_read_tsc(); control->int_ctl = V_INTR_MASKING_MASK; init_seg(&save->es); @@ -902,6 +901,7 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT; svm->asid_generation = 0; init_vmcb(svm); + svm->vmcb->control.tsc_offset = 0-native_read_tsc(); fx_init(&svm->vcpu); svm->vcpu.arch.apic_base = 0xfee00000 | MSR_IA32_APICBASE_ENABLE; -- cgit v1.2.3 From 85aa4285872f67bb21ecf7de0e467c57b4c6a976 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Thu, 14 Oct 2010 13:49:58 -0300 Subject: KVM: fix irqfd assign/deassign race commit 6bbfb2653177a00f70e57e53625502d43804fed0 upstream. I think I see the following (theoretical) race: During irqfd assign, we drop irqfds lock before we schedule inject work. Therefore, deassign running on another CPU could cause shutdown and flush to run before inject, causing user after free in inject. A simple fix it to schedule inject under the lock. Signed-off-by: Michael S. Tsirkin Acked-by: Gregory Haskins Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- virt/kvm/eventfd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c index b81f0ebbaaad..33993e38fced 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c @@ -217,7 +217,6 @@ kvm_irqfd_assign(struct kvm *kvm, int fd, int gsi) events = file->f_op->poll(file, &irqfd->pt); list_add_tail(&irqfd->list, &kvm->irqfds.items); - spin_unlock_irq(&kvm->irqfds.lock); /* * Check if there was an event already pending on the eventfd @@ -226,6 +225,8 @@ kvm_irqfd_assign(struct kvm *kvm, int fd, int gsi) if (events & POLLIN) schedule_work(&irqfd->inject); + spin_unlock_irq(&kvm->irqfds.lock); + /* * do not drop the file until the irqfd is fully initialized, otherwise * we might race against the POLLHUP -- cgit v1.2.3 From 8706a900f0c047b49e34918cdf2b23dc82c234d5 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Thu, 14 Oct 2010 13:49:59 -0300 Subject: KVM: Fix reboot on Intel hosts commit ca242ac9960dc61530e25a2c190e4e13fd5f1ecb upstream. When we reboot, we disable vmx extensions or otherwise INIT gets blocked. If a task on another cpu hits a vmx instruction, it will fault if vmx is disabled. We trap that to avoid a nasty oops and spin until the reboot completes. Problem is, we sleep with interrupts disabled. This blocks smp_send_stop() from running, and the reboot process halts. Fix by enabling interrupts before spinning. Signed-off-by: Avi Kivity Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- virt/kvm/kvm_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 277452851313..dd85e2998196 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1942,10 +1942,12 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, asmlinkage void kvm_handle_fault_on_reboot(void) { - if (kvm_rebooting) + if (kvm_rebooting) { /* spin while reset goes on */ + local_irq_enable(); while (true) ; + } /* Fault while not rebooting. We want the trace. */ BUG(); } -- cgit v1.2.3 From 3899bc97ac29d0e81af688574b2f39197d3d655a Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 17 Sep 2010 00:46:42 +0900 Subject: bsg: fix incorrect device_status value commit 478971600e47cb83ff2d3c63c5c24f2b04b0d6a1 upstream. bsg incorrectly returns sg's masked_status value for device_status. [jejb: fix up expression logic] Reported-by: Douglas Gilbert Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- block/bsg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/bsg.c b/block/bsg.c index 82d58829ba59..0c00870553a3 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -426,7 +426,7 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr, /* * fill in all the output members */ - hdr->device_status = status_byte(rq->errors); + hdr->device_status = rq->errors & 0xff; hdr->transport_status = host_byte(rq->errors); hdr->driver_status = driver_byte(rq->errors); hdr->info = 0; -- cgit v1.2.3 From 30756523ef2f21b917c7e85d2361f25488874c40 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Fri, 10 Sep 2010 01:20:27 -0400 Subject: Fix VPD inquiry page wrapper commit 16d3ea26f82271fef9b1c4523b5e1ea31fa39eec upstream. Fix two bugs in the VPD page wrapper: - Don't return failure if the user asked for page 0 - The end of buffer check failed to account for the page header size and consequently didn't work Signed-off-by: Martin K. Petersen Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index ad0ed212db4a..348fba0a8976 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -1046,13 +1046,13 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf, /* If the user actually wanted this page, we can skip the rest */ if (page == 0) - return -EINVAL; + return 0; for (i = 0; i < min((int)buf[3], buf_len - 4); i++) if (buf[i + 4] == page) goto found; - if (i < buf[3] && i > buf_len) + if (i < buf[3] && i >= buf_len - 4) /* ran off the end of the buffer, give us benefit of doubt */ goto found; /* The device claims it doesn't support the requested page */ -- cgit v1.2.3 From 64b4822a0e7ae4f54d3d23e860a17f5c1257e1ea Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Wed, 20 Oct 2010 13:45:43 +1030 Subject: virtio: console: Don't block entire guest if host doesn't read data commit 531295e63be8c2b8b909d7400739e8b8df60d61f upstream. If the host is slow in reading data or doesn't read data at all, blocking write calls not only blocked the program that called write() but the entire guest itself. To overcome this, let's not block till the host signals it has given back the virtio ring element we passed it. Instead, send the buffer to the host and return to userspace. This operation then becomes similar to how non-blocking writes work, so let's use the existing code for this path as well. This code change also ensures blocking write calls do get blocked if there's not enough room in the virtio ring as well as they don't return -EAGAIN to userspace. Signed-off-by: Amit Shah Acked-by: Hans de Goede Signed-off-by: Rusty Russell Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/char/virtio_console.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index c810481a5bc2..0f69c5ec0ecd 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -459,9 +459,12 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count, /* * Wait till the host acknowledges it pushed out the data we - * sent. This is done for ports in blocking mode or for data - * from the hvc_console; the tty operations are performed with - * spinlocks held so we can't sleep here. + * sent. This is done for data from the hvc_console; the tty + * operations are performed with spinlocks held so we can't + * sleep here. An alternative would be to copy the data to a + * buffer and relax the spinning requirement. The downside is + * we need to kmalloc a GFP_ATOMIC buffer each time the + * console driver writes something out. */ while (!virtqueue_get_buf(out_vq, &len)) cpu_relax(); @@ -626,6 +629,14 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, goto free_buf; } + /* + * We now ask send_buf() to not spin for generic ports -- we + * can re-use the same code path that non-blocking file + * descriptors take for blocking file descriptors since the + * wait is already done and we're certain the write will go + * through to the host. + */ + nonblock = true; ret = send_buf(port, buf, count, nonblock); if (nonblock && ret > 0) -- cgit v1.2.3 From 50c5f9ded08bf13cbef33ebbb19b78fc21b2861d Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 17 Sep 2010 23:26:24 -0700 Subject: ACPI: Handle ACPI0007 Device in acpi_early_set_pdc commit c1e0ddbf0a97e1704d7f13b4934f9acca002402d upstream. After | commit d8191fa4a33fdc817277da4f2b7f771ff605a41c | Author: Alex Chiang | Date: Mon Feb 22 12:11:39 2010 -0700 | | ACPI: processor: driver doesn't need to evaluate _PDC | | Now that the early _PDC evaluation path knows how to correctly | evaluate _PDC on only physically present processors, there's no | need for the processor driver to evaluate it later when it loads. | | To cover the hotplug case, push _PDC evaluation down into the | hotplug paths. only cpu with Processor Statement get processed with _PDC If bios is using Device object instead of Processor statement. SSDTs for Pstate/Cstate/Tstate can not be loaded dynamically. Need to try to scan ACPI0007 in addition to Processor. That commit is between 2.6.34-rc1 and 2.6.34-rc2, so stable tree for 2.6.34+ need this patch. Signed-off-by: Yinghai Lu Reviewed-by: Bjorn Helgaas Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/processor_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index e9699aaed109..df6e1676a6f3 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -352,4 +352,5 @@ void __init acpi_early_processor_set_pdc(void) acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, early_init_pdc, NULL, NULL, NULL); + acpi_get_devices("ACPI0007", early_init_pdc, NULL, NULL); } -- cgit v1.2.3 From 02f6f1e637a74a11bd5e834b39bc5e4dd28796c5 Mon Sep 17 00:00:00 2001 From: Matt Evans Date: Thu, 12 Aug 2010 20:58:28 +0000 Subject: powerpc: Initialise paca->kstack before early_setup_secondary commit f761622e59433130bc33ad086ce219feee9eb961 upstream. As early setup calls down to slb_initialize(), we must have kstack initialised before checking "should we add a bolted SLB entry for our kstack?" Failing to do so means stack access requires an SLB miss exception to refill an entry dynamically, if the stack isn't accessible via SLB(0) (kernel text & static data). It's not always allowable to take such a miss, and intermittent crashes will result. Primary CPUs don't have this issue; an SLB entry is not bolted for their stack anyway (as that lives within SLB(0)). This patch therefore only affects the init of secondaries. Signed-off-by: Matt Evans Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/head_64.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 844a44b64472..4d6681dce816 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -572,9 +572,6 @@ __secondary_start: /* Set thread priority to MEDIUM */ HMT_MEDIUM - /* Do early setup for that CPU (stab, slb, hash table pointer) */ - bl .early_setup_secondary - /* Initialize the kernel stack. Just a repeat for iSeries. */ LOAD_REG_ADDR(r3, current_set) sldi r28,r24,3 /* get current_set[cpu#] */ @@ -582,6 +579,9 @@ __secondary_start: addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD std r1,PACAKSAVE(r13) + /* Do early setup for that CPU (stab, slb, hash table pointer) */ + bl .early_setup_secondary + /* Clear backchain so we get nice backtraces */ li r7,0 mtlr r7 -- cgit v1.2.3 From 7837447f8b4372ccd19e3b28afff4c901edd3ae1 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Wed, 25 Aug 2010 21:04:25 +0000 Subject: powerpc: Don't use kernel stack with translation off commit 54a834043314c257210db2a9d59f8cc605571639 upstream. In f761622e59433130bc33ad086ce219feee9eb961 we changed early_setup_secondary so it's called using the proper kernel stack rather than the emergency one. Unfortunately, this stack pointer can't be used when translation is off on PHYP as this stack pointer might be outside the RMO. This results in the following on all non zero cpus: cpu 0x1: Vector: 300 (Data Access) at [c00000001639fd10] pc: 000000000001c50c lr: 000000000000821c sp: c00000001639ff90 msr: 8000000000001000 dar: c00000001639ffa0 dsisr: 42000000 current = 0xc000000016393540 paca = 0xc000000006e00200 pid = 0, comm = swapper The original patch was only tested on bare metal system, so it never caught this problem. This changes __secondary_start so that we calculate the new stack pointer but only start using it after we've called early_setup_secondary. With this patch, the above problem goes away. Signed-off-by: Michael Neuling Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/head_64.S | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 4d6681dce816..c571cd3c1453 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -575,13 +575,19 @@ __secondary_start: /* Initialize the kernel stack. Just a repeat for iSeries. */ LOAD_REG_ADDR(r3, current_set) sldi r28,r24,3 /* get current_set[cpu#] */ - ldx r1,r3,r28 - addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD - std r1,PACAKSAVE(r13) + ldx r14,r3,r28 + addi r14,r14,THREAD_SIZE-STACK_FRAME_OVERHEAD + std r14,PACAKSAVE(r13) /* Do early setup for that CPU (stab, slb, hash table pointer) */ bl .early_setup_secondary + /* + * setup the new stack pointer, but *don't* use this until + * translation is on. + */ + mr r1, r14 + /* Clear backchain so we get nice backtraces */ li r7,0 mtlr r7 -- cgit v1.2.3 From 073676f1efde423a75fbfcb3ff4e0cbfaddb7bdb Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Mon, 11 Oct 2010 15:45:35 -0700 Subject: b44: fix carrier detection on bind commit bcf64aa379fcadd074449cbf0c049da70071b06f upstream. For carrier detection to work properly when binding the driver with a cable unplugged, netif_carrier_off() should be called after register_netdev(), not before. Signed-off-by: Paul Fertser Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/b44.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 293f9c16e786..41737596c774 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -2168,8 +2168,6 @@ static int __devinit b44_init_one(struct ssb_device *sdev, dev->irq = sdev->irq; SET_ETHTOOL_OPS(dev, &b44_ethtool_ops); - netif_carrier_off(dev); - err = ssb_bus_powerup(sdev->bus, 0); if (err) { dev_err(sdev->dev, @@ -2209,6 +2207,8 @@ static int __devinit b44_init_one(struct ssb_device *sdev, goto err_out_powerdown; } + netif_carrier_off(dev); + ssb_set_drvdata(sdev, dev); /* Chip reset provides power to the b44 MAC & PCI cores, which -- cgit v1.2.3 From 6fe329402817c4b918afd5154c7708a77c65b500 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Thu, 17 Jun 2010 14:15:06 -0300 Subject: ALSA: hda - add ideapad model for Conexant 5051 codec commit f7154de220f14073ef0d76638f85e254ad2e202f upstream. Lenovo IdeaPad Y430 has an additional subwoofer connected at pin 0x1b, which isn't muted when headphone is plugged in. This adds additional support to the extra subwoofer via new ideapad model. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Takashi Iwai Cc: David Henningsson Signed-off-by: Greg Kroah-Hartman --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 + sound/pci/hda/patch_conexant.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index dc25bb84b83b..50faa7e96892 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -282,6 +282,7 @@ Conexant 5051 hp HP Spartan laptop hp-dv6736 HP dv6736 hp-f700 HP Compaq Presario F700 + ideapad Lenovo IdeaPad laptop lenovo-x200 Lenovo X200 laptop toshiba Toshiba Satellite M300 diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 4eee494e7e87..15ba418fe6a4 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -1633,6 +1633,11 @@ static void cxt5051_update_speaker(struct hda_codec *codec) pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl); + /* on ideapad there is an aditional speaker (subwoofer) to mute */ + if (spec->ideapad) + snd_hda_codec_write(codec, 0x1b, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, + pinctl); } /* turn on/off EAPD (+ mute HP) as a master switch */ @@ -1889,6 +1894,13 @@ static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid, #endif } +static struct hda_verb cxt5051_ideapad_init_verbs[] = { + /* Subwoofer */ + {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, + { } /* end */ +}; + /* initialize jack-sensing, too */ static int cxt5051_init(struct hda_codec *codec) { @@ -1918,6 +1930,7 @@ enum { CXT5051_LENOVO_X200, /* Lenovo X200 laptop, also used for Advanced Mini Dock 250410 */ CXT5051_F700, /* HP Compaq Presario F700 */ CXT5051_TOSHIBA, /* Toshiba M300 & co */ + CXT5051_IDEAPAD, /* Lenovo IdeaPad Y430 */ CXT5051_MODELS }; @@ -1928,6 +1941,7 @@ static const char *cxt5051_models[CXT5051_MODELS] = { [CXT5051_LENOVO_X200] = "lenovo-x200", [CXT5051_F700] = "hp-700", [CXT5051_TOSHIBA] = "toshiba", + [CXT5051_IDEAPAD] = "ideapad", }; static struct snd_pci_quirk cxt5051_cfg_tbl[] = { @@ -1939,6 +1953,7 @@ static struct snd_pci_quirk cxt5051_cfg_tbl[] = { CXT5051_LAPTOP), SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200), + SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo IdeaPad", CXT5051_IDEAPAD), {} }; @@ -2000,6 +2015,11 @@ static int patch_cxt5051(struct hda_codec *codec) spec->mixers[0] = cxt5051_toshiba_mixers; spec->auto_mic = AUTO_MIC_PORTB; break; + case CXT5051_IDEAPAD: + spec->init_verbs[spec->num_init_verbs++] = + cxt5051_ideapad_init_verbs; + spec->ideapad = 1; + break; } return 0; -- cgit v1.2.3 From e5668aa876cbfb73277a5d7272e96eef30ede0d5 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 2 Aug 2010 15:14:43 +0000 Subject: ACPI: enable repeated PCIEXP wakeup by clearing PCIEXP_WAKE_STS on resume commit 573b638158029898caf9470c8214b7ddd29751e3 upstream. Section 4.7.3.1.1 (PM1 Status Registers) of version 4.0 of the ACPI spec concerning PCIEXP_WAKE_STS points out in in the final note field in table 4-11 that if this bit is set to 1 and the system is put into a sleeping state then the system will not automatically wake. This bit gets set by hardware to indicate that the system woke up due to a PCI Express wakeup event, so clear it during acpi_hw_clear_acpi_status() calls to enable subsequent resumes to work. BugLink: http://bugs.launchpad.net/bugs/613381 Signed-off-by: Colin Ian King Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/acpica/aclocal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 147a7e6bd38f..9f82a38ed5b7 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -853,6 +853,7 @@ struct acpi_bit_register_info { ACPI_BITMASK_POWER_BUTTON_STATUS | \ ACPI_BITMASK_SLEEP_BUTTON_STATUS | \ ACPI_BITMASK_RT_CLOCK_STATUS | \ + ACPI_BITMASK_PCIEXP_WAKE_DISABLE | \ ACPI_BITMASK_WAKE_STATUS) #define ACPI_BITMASK_TIMER_ENABLE 0x0001 -- cgit v1.2.3 From 00f8646ef207c509072889c922d180cd28c923b9 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 24 Sep 2010 21:02:27 -0400 Subject: intel_idle: PCI quirk to prevent Lenovo Ideapad s10-3 boot hang commit 4731fdcf6f7bdab3e369a3f844d4ea4d4017284d upstream. When the Lenovo Ideapad S10-3 is booted with HT enabled, it hits a boot hang in the intel_idle driver. This occurs when entering ATM-C4 for the first time, unless BM_STS is first cleared. acpi_idle doesn't see this because it first checks and clears BM_STS, but it would hit the same hang if that check were disabled. http://bugs.meego.com/show_bug.cgi?id=7093 https://bugs.launchpad.net/ubuntu/+source/linux/+bug/634702 Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e28524ec7cee..2a73ceb35b32 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -149,6 +149,26 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_1, quirk_isa_d DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_dma_hangs); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs); +/* + * Intel NM10 "TigerPoint" LPC PM1a_STS.BM_STS must be clear + * for some HT machines to use C4 w/o hanging. + */ +static void __devinit quirk_tigerpoint_bm_sts(struct pci_dev *dev) +{ + u32 pmbase; + u16 pm1a; + + pci_read_config_dword(dev, 0x40, &pmbase); + pmbase = pmbase & 0xff80; + pm1a = inw(pmbase); + + if (pm1a & 0x10) { + dev_info(&dev->dev, FW_BUG "TigerPoint LPC.BM_STS cleared\n"); + outw(0x10, pmbase); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGP_LPC, quirk_tigerpoint_bm_sts); + /* * Chipsets where PCI->PCI transfers vanish or hang */ -- cgit v1.2.3 From 223c90ef801849ffb952ad2cc85b5eddf4082f61 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 28 Sep 2010 17:51:51 -0400 Subject: ACPI: EC: add Vista incompatibility DMI entry for Toshiba Satellite L355 commit 7a1d602f5fc35d14907b7da98d5627acb69589d1 upstream. https://bugzilla.kernel.org/show_bug.cgi?id=12641 Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/blacklist.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 2bb28b9d91c4..cd56db5e6c08 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -226,6 +226,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, }, { + .callback = dmi_disable_osi_vista, + .ident = "Toshiba Satellite L355", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"), + }, + }, + { .callback = dmi_disable_osi_win7, .ident = "ASUS K50IJ", .matches = { -- cgit v1.2.3 From 6d83ebffef9bf0d554eada20e0146981b6a4e83a Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 28 Sep 2010 17:20:20 -0400 Subject: ACPI: delete ZEPTO idle=nomwait DMI quirk commit 64a32307b710c100beb101e9c78f8022f0e8ba61 upstream. per comments in the bug report, this entry seems to hurt at much as it helps. https://bugzilla.kernel.org/show_bug.cgi?id=10807 Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/processor_core.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index df6e1676a6f3..bec561c14beb 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -28,12 +28,6 @@ static int set_no_mwait(const struct dmi_system_id *id) } static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { - { - set_no_mwait, "IFL91 board", { - DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), - DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"), - DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL}, { set_no_mwait, "Extensa 5220", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), -- cgit v1.2.3 From fe1a1f1554fd1b7f1afa95121dcd2a232eca72ca Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 28 Sep 2010 22:48:55 -0400 Subject: ACPI: Disable Windows Vista compatibility for Toshiba P305D commit 337279ce3aa85d81d34c0f837d1c204df105103b upstream. Disable the Windows Vista (SP1) compatibility for Toshiba P305D. http://bugzilla.kernel.org/show_bug.cgi?id=14736 Signed-off-by: Zhang Rui Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/blacklist.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index cd56db5e6c08..51cada7fcc5f 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -241,6 +241,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"), }, }, + { + .callback = dmi_disable_osi_vista, + .ident = "Toshiba P305D", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"), + }, + }, /* * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. -- cgit v1.2.3 From fc5ae3497e1abe79a3324a883b2c8799acc5a67b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 24 Sep 2010 16:46:14 -0400 Subject: PM / ACPI: Blacklist systems known to require acpi_sleep=nonvs commit 539986482b0db07b7164ab086d167ab99b4d3061 upstream. Commit 2a6b69765ad794389f2fc3e14a0afa1a995221c2 (ACPI: Store NVS state even when entering suspend to RAM) changed the ACPI suspend to RAM code so that the NVS memory area is always unconditionally saved during suspend and restored during resume, since some systems evidently need that for the suspend-resume to work on them. However, it turned out that this change broke suspend-resume on a few systems, so commit 72ad5d77fb981963edae15eee8196c80238f5ed0 (ACPI / Sleep: Allow the NVS saving to be skipped during suspend to RAM) introduced the acpi_sleep=nonvs command line switch to allow their users to work around this issue. To keep track of the systems that require this workaround and to make the life of their users slightly easier blacklist them in acpisleep_dmi_table[]. https://bugzilla.kernel.org/show_bug.cgi?id=16396 Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/sleep.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 2862c781b372..4882bc199ffd 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -362,6 +362,12 @@ static int __init init_old_suspend_ordering(const struct dmi_system_id *d) return 0; } +static int __init init_nvs_nosave(const struct dmi_system_id *d) +{ + acpi_nvs_nosave(); + return 0; +} + static struct dmi_system_id __initdata acpisleep_dmi_table[] = { { .callback = init_old_suspend_ordering, @@ -396,6 +402,22 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), }, }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-SR11M", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Everex StepNote Series", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ -- cgit v1.2.3 From 6b85aae5dfa34321a2336f57109cd9ad4ae1bb51 Mon Sep 17 00:00:00 2001 From: Jacob Pan Date: Wed, 19 May 2010 12:01:23 -0700 Subject: x86: detect scattered cpuid features earlier commit 1dedefd1a066a795a87afca9c0236e1a94de9bf6 upstream. Some extra CPU features such as ARAT is needed in early boot so that x86_init function pointers can be set up properly. http://lkml.org/lkml/2010/5/18/519 At start_kernel() level, this patch moves init_scattered_cpuid_features() from check_bugs() to setup_arch() -> early_cpu_init() which is earlier than platform specific x86_init layer setup. Suggested by HPA. Signed-off-by: Jacob Pan LKML-Reference: <1274295685-6774-2-git-send-email-jacob.jun.pan@linux.intel.com> Acked-by: Thomas Gleixner Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 296170084c80..d938871e3d83 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -576,6 +576,7 @@ void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) if (c->extended_cpuid_level >= 0x80000007) c->x86_power = cpuid_edx(0x80000007); + init_scattered_cpuid_features(c); } static void __cpuinit identify_cpu_without_cpuid(struct cpuinfo_x86 *c) @@ -731,7 +732,6 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) get_model_name(c); /* Default name */ - init_scattered_cpuid_features(c); detect_nopl(c); } -- cgit v1.2.3 From c4cf17f1e6a95168d479656d066c5b8324c16b06 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Fri, 27 Aug 2010 11:08:57 +0800 Subject: agp/intel: Fix cache control for Sandybridge commit f8f235e5bbf4e61f3e0886a44afb1dc4cfe8f337 upstream. Sandybridge GTT has new cache control bits in PTE, which controls graphics page cache in LLC or LLC/MLC, so we need to extend the mask function to respect the new bits. And set cache control to always LLC only by default on Gen6. Signed-off-by: Zhenyu Wang Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/char/agp/intel-agp.c | 1 + drivers/char/agp/intel-agp.h | 6 +++++ drivers/char/agp/intel-gtt.c | 50 ++++++++++++++++++++++++++++++++--------- drivers/gpu/drm/i915/i915_gem.c | 1 + include/linux/intel-gtt.h | 20 +++++++++++++++++ 5 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 include/linux/intel-gtt.h diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index adc0f8931702..41871211e5d1 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -12,6 +12,7 @@ #include #include "agp.h" #include "intel-agp.h" +#include #include "intel-gtt.c" diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index bc9a4ad3bbd3..4c8949af35a1 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -60,6 +60,12 @@ #define I810_PTE_LOCAL 0x00000002 #define I810_PTE_VALID 0x00000001 #define I830_PTE_SYSTEM_CACHED 0x00000006 +/* GT PTE cache control fields */ +#define GEN6_PTE_UNCACHED 0x00000002 +#define GEN6_PTE_LLC 0x00000004 +#define GEN6_PTE_LLC_MLC 0x00000006 +#define GEN6_PTE_GFDT 0x00000008 + #define I810_SMRAM_MISCC 0x70 #define I810_GFX_MEM_WIN_SIZE 0x00010000 #define I810_GFX_MEM_WIN_32M 0x00010000 diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index ed11c770c9ab..86f5337aabdf 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -49,6 +49,26 @@ static struct gatt_mask intel_i810_masks[] = .type = INTEL_AGP_CACHED_MEMORY} }; +#define INTEL_AGP_UNCACHED_MEMORY 0 +#define INTEL_AGP_CACHED_MEMORY_LLC 1 +#define INTEL_AGP_CACHED_MEMORY_LLC_GFDT 2 +#define INTEL_AGP_CACHED_MEMORY_LLC_MLC 3 +#define INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT 4 + +static struct gatt_mask intel_gen6_masks[] = +{ + {.mask = I810_PTE_VALID | GEN6_PTE_UNCACHED, + .type = INTEL_AGP_UNCACHED_MEMORY }, + {.mask = I810_PTE_VALID | GEN6_PTE_LLC, + .type = INTEL_AGP_CACHED_MEMORY_LLC }, + {.mask = I810_PTE_VALID | GEN6_PTE_LLC | GEN6_PTE_GFDT, + .type = INTEL_AGP_CACHED_MEMORY_LLC_GFDT }, + {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC, + .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC }, + {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC | GEN6_PTE_GFDT, + .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT }, +}; + static struct _intel_private { struct pci_dev *pcidev; /* device one */ u8 __iomem *registers; @@ -175,13 +195,6 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem, off_t pg_start, int mask_type) { int i, j; - u32 cache_bits = 0; - - if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) - { - cache_bits = I830_PTE_SYSTEM_CACHED; - } for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { writel(agp_bridge->driver->mask_memory(agp_bridge, @@ -314,6 +327,23 @@ static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge, return 0; } +static int intel_gen6_type_to_mask_type(struct agp_bridge_data *bridge, + int type) +{ + unsigned int type_mask = type & ~AGP_USER_CACHED_MEMORY_GFDT; + unsigned int gfdt = type & AGP_USER_CACHED_MEMORY_GFDT; + + if (type_mask == AGP_USER_UNCACHED_MEMORY) + return INTEL_AGP_UNCACHED_MEMORY; + else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) + return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT : + INTEL_AGP_CACHED_MEMORY_LLC_MLC; + else /* set 'normal'/'cached' to LLC by default */ + return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_GFDT : + INTEL_AGP_CACHED_MEMORY_LLC; +} + + static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, int type) { @@ -1155,7 +1185,7 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start, mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); - if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY && + if (!IS_SNB && mask_type != 0 && mask_type != AGP_PHYS_MEMORY && mask_type != INTEL_AGP_CACHED_MEMORY) goto out_err; @@ -1546,7 +1576,7 @@ static const struct agp_bridge_driver intel_gen6_driver = { .fetch_size = intel_i9xx_fetch_size, .cleanup = intel_i915_cleanup, .mask_memory = intel_gen6_mask_memory, - .masks = intel_i810_masks, + .masks = intel_gen6_masks, .agp_enable = intel_i810_agp_enable, .cache_flush = global_cache_flush, .create_gatt_table = intel_i965_create_gatt_table, @@ -1559,7 +1589,7 @@ static const struct agp_bridge_driver intel_gen6_driver = { .agp_alloc_pages = agp_generic_alloc_pages, .agp_destroy_page = agp_generic_destroy_page, .agp_destroy_pages = agp_generic_destroy_pages, - .agp_type_to_mask_type = intel_i830_type_to_mask_type, + .agp_type_to_mask_type = intel_gen6_type_to_mask_type, .chipset_flush = intel_i915_chipset_flush, #ifdef USE_PCI_DMA_API .agp_map_page = intel_agp_map_page, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 50e6984f3572..dc5d2efc57c1 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -34,6 +34,7 @@ #include #include #include +#include static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); diff --git a/include/linux/intel-gtt.h b/include/linux/intel-gtt.h new file mode 100644 index 000000000000..1d19ab2afa39 --- /dev/null +++ b/include/linux/intel-gtt.h @@ -0,0 +1,20 @@ +/* + * Common Intel AGPGART and GTT definitions. + */ +#ifndef _INTEL_GTT_H +#define _INTEL_GTT_H + +#include + +/* This is for Intel only GTT controls. + * + * Sandybridge: AGP_USER_CACHED_MEMORY default to LLC only + */ + +#define AGP_USER_CACHED_MEMORY_LLC_MLC (AGP_USER_TYPES + 2) +#define AGP_USER_UNCACHED_MEMORY (AGP_USER_TYPES + 4) + +/* flag for GFDT type */ +#define AGP_USER_CACHED_MEMORY_GFDT (1 << 3) + +#endif -- cgit v1.2.3 From ba8f2de53b32dc1f13b60dab2f9fee563e5c73bd Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 16 Aug 2010 14:38:33 +0200 Subject: x86-32: Separate 1:1 pagetables from swapper_pg_dir commit fd89a137924e0710078c3ae855e7cec1c43cb845 upstream. This patch fixes machine crashes which occur when heavily exercising the CPU hotplug codepaths on a 32-bit kernel. These crashes are caused by AMD Erratum 383 and result in a fatal machine check exception. Here's the scenario: 1. On 32-bit, the swapper_pg_dir page table is used as the initial page table for booting a secondary CPU. 2. To make this work, swapper_pg_dir needs a direct mapping of physical memory in it (the low mappings). By adding those low, large page (2M) mappings (PAE kernel), we create the necessary conditions for Erratum 383 to occur. 3. Other CPUs which do not participate in the off- and onlining game may use swapper_pg_dir while the low mappings are present (when leave_mm is called). For all steps below, the CPU referred to is a CPU that is using swapper_pg_dir, and not the CPU which is being onlined. 4. The presence of the low mappings in swapper_pg_dir can result in TLB entries for addresses below __PAGE_OFFSET to be established speculatively. These TLB entries are marked global and large. 5. When the CPU with such TLB entry switches to another page table, this TLB entry remains because it is global. 6. The process then generates an access to an address covered by the above TLB entry but there is a permission mismatch - the TLB entry covers a large global page not accessible to userspace. 7. Due to this permission mismatch a new 4kb, user TLB entry gets established. Further, Erratum 383 provides for a small window of time where both TLB entries are present. This results in an uncorrectable machine check exception signalling a TLB multimatch which panics the machine. There are two ways to fix this issue: 1. Always do a global TLB flush when a new cr3 is loaded and the old page table was swapper_pg_dir. I consider this a hack hard to understand and with performance implications 2. Do not use swapper_pg_dir to boot secondary CPUs like 64-bit does. This patch implements solution 2. It introduces a trampoline_pg_dir which has the same layout as swapper_pg_dir with low_mappings. This page table is used as the initial page table of the booting CPU. Later in the bringup process, it switches to swapper_pg_dir and does a global TLB flush. This fixes the crashes in our test cases. -v2: switch to swapper_pg_dir right after entering start_secondary() so that we are able to access percpu data which might not be mapped in the trampoline page table. Signed-off-by: Joerg Roedel LKML-Reference: <20100816123833.GB28147@aftab> Signed-off-by: Borislav Petkov Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/pgtable_32.h | 1 + arch/x86/include/asm/trampoline.h | 3 +++ arch/x86/kernel/head_32.S | 8 +++++++- arch/x86/kernel/setup.c | 2 ++ arch/x86/kernel/smpboot.c | 32 +++++++++++++------------------- arch/x86/kernel/trampoline.c | 18 ++++++++++++++++++ 6 files changed, 44 insertions(+), 20 deletions(-) diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index 2984a25ff383..f686f49e8b7b 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -26,6 +26,7 @@ struct mm_struct; struct vm_area_struct; extern pgd_t swapper_pg_dir[1024]; +extern pgd_t trampoline_pg_dir[1024]; static inline void pgtable_cache_init(void) { } static inline void check_pgt_cache(void) { } diff --git a/arch/x86/include/asm/trampoline.h b/arch/x86/include/asm/trampoline.h index cb507bb05d79..8f78fdf3f178 100644 --- a/arch/x86/include/asm/trampoline.h +++ b/arch/x86/include/asm/trampoline.h @@ -13,14 +13,17 @@ extern unsigned char *trampoline_base; extern unsigned long init_rsp; extern unsigned long initial_code; +extern unsigned long initial_page_table; extern unsigned long initial_gs; #define TRAMPOLINE_SIZE roundup(trampoline_end - trampoline_data, PAGE_SIZE) extern unsigned long setup_trampoline(void); +extern void __init setup_trampoline_page_table(void); extern void __init reserve_trampoline_memory(void); #else static inline void reserve_trampoline_memory(void) {}; +extern void __init setup_trampoline_page_table(void) {}; #endif /* CONFIG_X86_TRAMPOLINE */ #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 37c3d4b17d85..75e398199643 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -328,7 +328,7 @@ ENTRY(startup_32_smp) /* * Enable paging */ - movl $pa(swapper_pg_dir),%eax + movl pa(initial_page_table), %eax movl %eax,%cr3 /* set the page table pointer.. */ movl %cr0,%eax orl $X86_CR0_PG,%eax @@ -608,6 +608,8 @@ ignore_int: .align 4 ENTRY(initial_code) .long i386_start_kernel +ENTRY(initial_page_table) + .long pa(swapper_pg_dir) /* * BSS section @@ -623,6 +625,10 @@ ENTRY(swapper_pg_dir) #endif swapper_pg_fixmap: .fill 1024,4,0 +#ifdef CONFIG_X86_TRAMPOLINE +ENTRY(trampoline_pg_dir) + .fill 1024,4,0 +#endif ENTRY(empty_zero_page) .fill 4096,1,0 diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index b4ae4acbd031..6600cfde6b7c 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1008,6 +1008,8 @@ void __init setup_arch(char **cmdline_p) paging_init(); x86_init.paging.pagetable_setup_done(swapper_pg_dir); + setup_trampoline_page_table(); + tboot_probe(); #ifdef CONFIG_X86_64 diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 0bf2ece9982f..821ee1b7634e 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -73,7 +73,6 @@ #ifdef CONFIG_X86_32 u8 apicid_2_node[MAX_APICID]; -static int low_mappings; #endif /* State of each CPU */ @@ -300,6 +299,18 @@ notrace static void __cpuinit start_secondary(void *unused) * fragile that we want to limit the things done here to the * most necessary things. */ + +#ifdef CONFIG_X86_32 + /* + * Switch away from the trampoline page-table + * + * Do this before cpu_init() because it needs to access per-cpu + * data which may not be mapped in the trampoline page-table. + */ + load_cr3(swapper_pg_dir); + __flush_tlb_all(); +#endif + vmi_bringup(); cpu_init(); preempt_disable(); @@ -318,12 +329,6 @@ notrace static void __cpuinit start_secondary(void *unused) legacy_pic->chip->unmask(0); } -#ifdef CONFIG_X86_32 - while (low_mappings) - cpu_relax(); - __flush_tlb_all(); -#endif - /* This must be done before setting cpu_online_mask */ set_cpu_sibling_map(raw_smp_processor_id()); wmb(); @@ -773,6 +778,7 @@ do_rest: #ifdef CONFIG_X86_32 /* Stack for startup_32 can be just as for start_secondary onwards */ irq_ctx_init(cpu); + initial_page_table = __pa(&trampoline_pg_dir); #else clear_tsk_thread_flag(c_idle.idle, TIF_FORK); initial_gs = per_cpu_offset(cpu); @@ -920,20 +926,8 @@ int __cpuinit native_cpu_up(unsigned int cpu) per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; -#ifdef CONFIG_X86_32 - /* init low mem mapping */ - clone_pgd_range(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY, - min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY)); - flush_tlb_all(); - low_mappings = 1; - err = do_boot_cpu(apicid, cpu); - zap_low_mappings(false); - low_mappings = 0; -#else - err = do_boot_cpu(apicid, cpu); -#endif if (err) { pr_debug("do_boot_cpu failed %d\n", err); return -EIO; diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c index c652ef62742d..a874495b3673 100644 --- a/arch/x86/kernel/trampoline.c +++ b/arch/x86/kernel/trampoline.c @@ -1,6 +1,7 @@ #include #include +#include #include #if defined(CONFIG_X86_64) && defined(CONFIG_ACPI_SLEEP) @@ -37,3 +38,20 @@ unsigned long __trampinit setup_trampoline(void) memcpy(trampoline_base, trampoline_data, TRAMPOLINE_SIZE); return virt_to_phys(trampoline_base); } + +void __init setup_trampoline_page_table(void) +{ +#ifdef CONFIG_X86_32 + /* Copy kernel address range */ + clone_pgd_range(trampoline_pg_dir + KERNEL_PGD_BOUNDARY, + swapper_pg_dir + KERNEL_PGD_BOUNDARY, + min_t(unsigned long, KERNEL_PGD_PTRS, + KERNEL_PGD_BOUNDARY)); + + /* Initialize low mappings */ + clone_pgd_range(trampoline_pg_dir, + swapper_pg_dir + KERNEL_PGD_BOUNDARY, + min_t(unsigned long, KERNEL_PGD_PTRS, + KERNEL_PGD_BOUNDARY)); +#endif +} -- cgit v1.2.3 From d521d5c586bf14422927a3574d921b0f4af19023 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 18 Aug 2010 11:42:23 -0700 Subject: x86-32: Fix dummy trampoline-related inline stubs commit 8848a91068c018bc91f597038a0f41462a0f88a4 upstream. Fix dummy inline stubs for trampoline-related functions when no trampolines exist (until we get rid of the no-trampoline case entirely.) Signed-off-by: H. Peter Anvin Cc: Joerg Roedel Cc: Borislav Petkov LKML-Reference: <4C6C294D.3030404@zytor.com> Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/trampoline.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/trampoline.h b/arch/x86/include/asm/trampoline.h index 8f78fdf3f178..4dde797c0578 100644 --- a/arch/x86/include/asm/trampoline.h +++ b/arch/x86/include/asm/trampoline.h @@ -22,8 +22,8 @@ extern unsigned long setup_trampoline(void); extern void __init setup_trampoline_page_table(void); extern void __init reserve_trampoline_memory(void); #else -static inline void reserve_trampoline_memory(void) {}; -extern void __init setup_trampoline_page_table(void) {}; +static inline void setup_trampoline_page_table(void) {} +static inline void reserve_trampoline_memory(void) {} #endif /* CONFIG_X86_TRAMPOLINE */ #endif /* __ASSEMBLY__ */ -- cgit v1.2.3 From 39f477027fc8ed0115b2c73ec2a3d53f33e0d35e Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Tue, 24 Aug 2010 22:44:12 -0700 Subject: x86, mm: Fix CONFIG_VMSPLIT_1G and 2G_OPT trampoline commit b7d460897739e02f186425b7276e3fdb1595cea7 upstream. rc2 kernel crashes when booting second cpu on this CONFIG_VMSPLIT_2G_OPT laptop: whereas cloning from kernel to low mappings pgd range does need to limit by both KERNEL_PGD_PTRS and KERNEL_PGD_BOUNDARY, cloning kernel pgd range itself must not be limited by the smaller KERNEL_PGD_BOUNDARY. Signed-off-by: Hugh Dickins LKML-Reference: Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/trampoline.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c index a874495b3673..e2a595257390 100644 --- a/arch/x86/kernel/trampoline.c +++ b/arch/x86/kernel/trampoline.c @@ -45,8 +45,7 @@ void __init setup_trampoline_page_table(void) /* Copy kernel address range */ clone_pgd_range(trampoline_pg_dir + KERNEL_PGD_BOUNDARY, swapper_pg_dir + KERNEL_PGD_BOUNDARY, - min_t(unsigned long, KERNEL_PGD_PTRS, - KERNEL_PGD_BOUNDARY)); + KERNEL_PGD_PTRS); /* Initialize low mappings */ clone_pgd_range(trampoline_pg_dir, -- cgit v1.2.3 From a376eaa89e3931a4088deb6ef5d94569688efec0 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 7 Sep 2010 19:35:49 -0700 Subject: setup_arg_pages: diagnose excessive argument size commit 1b528181b2ffa14721fb28ad1bd539fe1732c583 upstream. The CONFIG_STACK_GROWSDOWN variant of setup_arg_pages() does not check the size of the argument/environment area on the stack. When it is unworkably large, shift_arg_pages() hits its BUG_ON. This is exploitable with a very large RLIMIT_STACK limit, to create a crash pretty easily. Check that the initial stack is not too large to make it possible to map in any executable. We're not checking that the actual executable (or intepreter, for binfmt_elf) will fit. So those mappings might clobber part of the initial stack mapping. But that is just userland lossage that userland made happen, not a kernel problem. Signed-off-by: Roland McGrath Reviewed-by: KOSAKI Motohiro Signed-off-by: Linus Torvalds Cc: Chuck Ebbert Signed-off-by: Greg Kroah-Hartman --- fs/exec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/exec.c b/fs/exec.c index e19de6a80339..f1bb0d21d080 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -594,6 +594,11 @@ int setup_arg_pages(struct linux_binprm *bprm, #else stack_top = arch_align_stack(stack_top); stack_top = PAGE_ALIGN(stack_top); + + if (unlikely(stack_top < mmap_min_addr) || + unlikely(vma->vm_end - vma->vm_start >= stack_top - mmap_min_addr)) + return -ENOMEM; + stack_shift = vma->vm_end - stack_top; bprm->p -= stack_shift; -- cgit v1.2.3 From c7d3b6415c472deae3fab07d06239abba9070c93 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 7 Sep 2010 19:36:28 -0700 Subject: execve: improve interactivity with large arguments commit 7993bc1f4663c0db67bb8f0d98e6678145b387cd upstream. This adds a preemption point during the copying of the argument and environment strings for execve, in copy_strings(). There is already a preemption point in the count() loop, so this doesn't add any new points in the abstract sense. When the total argument+environment strings are very large, the time spent copying them can be much more than a normal user time slice. So this change improves the interactivity of the rest of the system when one process is doing an execve with very large arguments. Signed-off-by: Roland McGrath Reviewed-by: KOSAKI Motohiro Signed-off-by: Linus Torvalds Cc: Chuck Ebbert Signed-off-by: Greg Kroah-Hartman --- fs/exec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/exec.c b/fs/exec.c index f1bb0d21d080..e8214175cbaa 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -420,6 +420,8 @@ static int copy_strings(int argc, char __user * __user * argv, while (len > 0) { int offset, bytes_to_copy; + cond_resched(); + offset = pos % PAGE_SIZE; if (offset == 0) offset = PAGE_SIZE; -- cgit v1.2.3 From e4037861387fe89ac082e8cf092b6a7bada09cb5 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 7 Sep 2010 19:37:06 -0700 Subject: execve: make responsive to SIGKILL with large arguments commit 9aea5a65aa7a1af9a4236dfaeb0088f1624f9919 upstream. An execve with a very large total of argument/environment strings can take a really long time in the execve system call. It runs uninterruptibly to count and copy all the strings. This change makes it abort the exec quickly if sent a SIGKILL. Note that this is the conservative change, to interrupt only for SIGKILL, by using fatal_signal_pending(). It would be perfectly correct semantics to let any signal interrupt the string-copying in execve, i.e. use signal_pending() instead of fatal_signal_pending(). We'll save that change for later, since it could have user-visible consequences, such as having a timer set too quickly make it so that an execve can never complete, though it always happened to work before. Signed-off-by: Roland McGrath Reviewed-by: KOSAKI Motohiro Cc: Chuck Ebbert Signed-off-by: Linus Torvalds --- fs/exec.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/exec.c b/fs/exec.c index e8214175cbaa..956bd37743cd 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -377,6 +377,9 @@ static int count(char __user * __user * argv, int max) argv++; if (i++ >= max) return -E2BIG; + + if (fatal_signal_pending(current)) + return -ERESTARTNOHAND; cond_resched(); } } @@ -420,6 +423,10 @@ static int copy_strings(int argc, char __user * __user * argv, while (len > 0) { int offset, bytes_to_copy; + if (fatal_signal_pending(current)) { + ret = -ERESTARTNOHAND; + goto out; + } cond_resched(); offset = pos % PAGE_SIZE; -- cgit v1.2.3 From 5daf133f0fb96925541cb5bf82317793a75c19f9 Mon Sep 17 00:00:00 2001 From: Stefan Bader Date: Tue, 31 Aug 2010 15:52:27 +0200 Subject: mm: Move vma_stack_continue into mm.h commit 39aa3cb3e8250db9188a6f1e3fb62ffa1a717678 upstream. So it can be used by all that need to check for that. Signed-off-by: Stefan Bader Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/proc/task_mmu.c | 3 ++- include/linux/mm.h | 6 ++++++ mm/mlock.c | 6 ------ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 439fc1f1c1c4..271afc48b9a5 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -224,7 +224,8 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) /* We don't show the stack guard page in /proc/maps */ start = vma->vm_start; if (vma->vm_flags & VM_GROWSDOWN) - start += PAGE_SIZE; + if (!vma_stack_continue(vma->vm_prev, vma->vm_start)) + start += PAGE_SIZE; seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", start, diff --git a/include/linux/mm.h b/include/linux/mm.h index c1f54d2c63d0..a724d896a38f 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -863,6 +863,12 @@ int set_page_dirty(struct page *page); int set_page_dirty_lock(struct page *page); int clear_page_dirty_for_io(struct page *page); +/* Is the vma a continuation of the stack vma above it? */ +static inline int vma_stack_continue(struct vm_area_struct *vma, unsigned long addr) +{ + return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN); +} + extern unsigned long move_page_tables(struct vm_area_struct *vma, unsigned long old_addr, struct vm_area_struct *new_vma, unsigned long new_addr, unsigned long len); diff --git a/mm/mlock.c b/mm/mlock.c index cbae7c5b9568..b70919ce4f72 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -135,12 +135,6 @@ void munlock_vma_page(struct page *page) } } -/* Is the vma a continuation of the stack vma above it? */ -static inline int vma_stack_continue(struct vm_area_struct *vma, unsigned long addr) -{ - return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN); -} - static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr) { return (vma->vm_flags & VM_GROWSDOWN) && -- cgit v1.2.3 From f16e6e4df8ec41328d7e0841bc17f2a587eb2c67 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 28 Oct 2010 21:52:43 -0700 Subject: Linux 2.6.35.8 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4c397f4168da..a15479163a1c 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 35 -EXTRAVERSION = .7 +EXTRAVERSION = .8 NAME = Yokohama # *DOCUMENTATION* -- cgit v1.2.3 From 12b1e06af306d6190cc7e8cccc8a328014e7c487 Mon Sep 17 00:00:00 2001 From: Max Vozeler Date: Tue, 21 Sep 2010 17:31:40 +0200 Subject: staging: usbip: Notify usb core of port status changes commit 0c9a32f0192e656daa2ff3c9149f6d71b4a1b873 upstream. This patch changes vhci to behave like dummy and other hcds when disconnecting a device. Previously detaching a device from the root hub did not notify the usb core of the disconnect and left the device visible. Signed-off-by: Max Vozeler Reported-by: Marco Lancione Tested-by: Luc Jalbert Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/vhci_hcd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index be5d8db98165..b6c871c6d5c0 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -164,6 +164,8 @@ void rh_port_disconnect(int rhport) * spin_unlock(&vdev->ud.lock); */ spin_unlock_irqrestore(&the_controller->lock, flags); + + usb_hcd_poll_rh_status(vhci_to_hcd(the_controller)); } -- cgit v1.2.3 From 0fa89f1c349b48e96a28e4270f2289332270f328 Mon Sep 17 00:00:00 2001 From: Max Vozeler Date: Tue, 21 Sep 2010 17:43:30 +0200 Subject: staging: usbip: Process event flags without delay commit 584c5b7cf06194464240280483ee0376cdddbbae upstream. The way the event handler works can cause it to delay events until eventual wakeup for another event. For example, on device detach (vhci): - Write to sysfs detach file -> usbip_event_add(VDEV_EVENT_DOWN) -> wakeup() #define VDEV_EVENT_DOWN (USBIP_EH_SHUTDOWN | USBIP_EH_RESET). - Event thread wakes up and passes the event to event_handler() to process. - It processes and clears the USBIP_EH_SHUTDOWN flag then returns. - The outer event loop (event_handler_loop()) calls wait_event_interruptible(). The processing of the second flag which is part of VDEV_EVENT_DOWN (USBIP_EH_RESET) did not happen yet. It is delayed until the next event. This means the ->reset callback may not happen for a long time (if ever), leaving the usbip port in a weird state which prevents its reuse. This patch changes the handler to process all flags before waiting for another wakeup. I have verified this change to fix a problem which prevented reattach of a usbip device. It also helps for socket errors which missed the RESET as well. The delayed event processing also affects the stub side of usbip and the error handling there. Signed-off-by: Max Vozeler Reported-by: Marco Lancione Tested-by: Luc Jalbert Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/usbip_event.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/staging/usbip/usbip_event.c b/drivers/staging/usbip/usbip_event.c index a2566f1075d5..af3832b03e4b 100644 --- a/drivers/staging/usbip/usbip_event.c +++ b/drivers/staging/usbip/usbip_event.c @@ -38,21 +38,13 @@ static int event_handler(struct usbip_device *ud) ud->eh_ops.shutdown(ud); ud->event &= ~USBIP_EH_SHUTDOWN; - - break; } - /* Stop the error handler. */ - if (ud->event & USBIP_EH_BYE) - return -1; - /* Reset the device. */ if (ud->event & USBIP_EH_RESET) { ud->eh_ops.reset(ud); ud->event &= ~USBIP_EH_RESET; - - break; } /* Mark the device as unusable. */ @@ -60,13 +52,11 @@ static int event_handler(struct usbip_device *ud) ud->eh_ops.unusable(ud); ud->event &= ~USBIP_EH_UNUSABLE; - - break; } - /* NOTREACHED */ - printk(KERN_ERR "%s: unknown event\n", __func__); - return -1; + /* Stop the error handler. */ + if (ud->event & USBIP_EH_BYE) + return -1; } return 0; -- cgit v1.2.3 From 2a64ff4337bc785563d187ddbfe4385888bda665 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 9 Oct 2010 13:26:12 -0700 Subject: Staging: phison: fix problem caused by libata change commit cf10700bf8047f0668dd874b607f89516612e6c7 upstream. The libata core changed this function so it needed to call a different one. See https://bugzilla.kernel.org/show_bug.cgi?id=19872 for details. Reported-by: Heinz Wiesinger Tested-by: Heinz Wiesinger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/phison/phison.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/phison/phison.c b/drivers/staging/phison/phison.c index 42783d7367e3..677152044f45 100644 --- a/drivers/staging/phison/phison.c +++ b/drivers/staging/phison/phison.c @@ -62,7 +62,7 @@ static int phison_init_one(struct pci_dev *pdev, const struct pci_device_id *id) }; const struct ata_port_info *ppi[] = { &info, NULL }; - ret = ata_pci_sff_init_one(pdev, ppi, &phison_sht, NULL, 0); + ret = ata_pci_bmdma_init_one(pdev, ppi, &phison_sht, NULL, 0); dev_dbg(&pdev->dev, "phison_init_one(), ret = %x\n", ret); -- cgit v1.2.3 From cef2c20c88c122f0dea3dadcc56bcdc0077061c4 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Fri, 15 Oct 2010 15:15:01 +0200 Subject: perf_events: Fix bogus AMD64 generic TLB events commit ba0cef3d149ce4db293c572bf36ed352b11ce7b9 upstream. PERF_COUNT_HW_CACHE_DTLB:READ:MISS had a bogus umask value of 0 which counts nothing. Needed to be 0x7 (to count all possibilities). PERF_COUNT_HW_CACHE_ITLB:READ:MISS had a bogus umask value of 0 which counts nothing. Needed to be 0x3 (to count all possibilities). Signed-off-by: Stephane Eranian Signed-off-by: Peter Zijlstra Cc: Robert Richter LKML-Reference: <4cb85478.41e9d80a.44e2.3f00@mx.google.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/perf_event_amd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c index c2897b7b4a3b..46d58448c3af 100644 --- a/arch/x86/kernel/cpu/perf_event_amd.c +++ b/arch/x86/kernel/cpu/perf_event_amd.c @@ -52,7 +52,7 @@ static __initconst const u64 amd_hw_cache_event_ids [ C(DTLB) ] = { [ C(OP_READ) ] = { [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses */ - [ C(RESULT_MISS) ] = 0x0046, /* L1 DTLB and L2 DLTB Miss */ + [ C(RESULT_MISS) ] = 0x0746, /* L1_DTLB_AND_L2_DLTB_MISS.ALL */ }, [ C(OP_WRITE) ] = { [ C(RESULT_ACCESS) ] = 0, @@ -66,7 +66,7 @@ static __initconst const u64 amd_hw_cache_event_ids [ C(ITLB) ] = { [ C(OP_READ) ] = { [ C(RESULT_ACCESS) ] = 0x0080, /* Instruction fecthes */ - [ C(RESULT_MISS) ] = 0x0085, /* Instr. fetch ITLB misses */ + [ C(RESULT_MISS) ] = 0x0385, /* L1_ITLB_AND_L2_ITLB_MISS.ALL */ }, [ C(OP_WRITE) ] = { [ C(RESULT_ACCESS) ] = -1, -- cgit v1.2.3 From c119599ec7d46c1b31d09a7968566b76e54da8e8 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Fri, 15 Oct 2010 15:26:01 +0200 Subject: perf_events: Fix bogus context time tracking commit c530ccd9a1864a44a7ff35826681229ce9f2357a upstream. You can only call update_context_time() when the context is active, i.e., the thread it is attached to is still running. However, perf_event_read() can be called even when the context is inactive, e.g., user read() the counters. The call to update_context_time() must be conditioned on the status of the context, otherwise, bogus time_enabled, time_running may be returned. Here is an example on AMD64. The task program is an example from libpfm4. The -p prints deltas every 1s. $ task -p -e cpu_clk_unhalted sleep 5 2,266,610 cpu_clk_unhalted (0.00% scaling, ena=2,158,982, run=2,158,982) 0 cpu_clk_unhalted (0.00% scaling, ena=2,158,982, run=2,158,982) 0 cpu_clk_unhalted (0.00% scaling, ena=2,158,982, run=2,158,982) 0 cpu_clk_unhalted (0.00% scaling, ena=2,158,982, run=2,158,982) 0 cpu_clk_unhalted (0.00% scaling, ena=2,158,982, run=2,158,982) 5,242,358,071 cpu_clk_unhalted (99.95% scaling, ena=5,000,359,984, run=2,319,270) Whereas if you don't read deltas, e.g., no call to perf_event_read() until the process terminates: $ task -e cpu_clk_unhalted sleep 5 2,497,783 cpu_clk_unhalted (0.00% scaling, ena=2,376,899, run=2,376,899) Notice that time_enable, time_running are bogus in the first example causing bogus scaling. This patch fixes the problem, by conditionally calling update_context_time() in perf_event_read(). Signed-off-by: Stephane Eranian Signed-off-by: Peter Zijlstra LKML-Reference: <4cb856dc.51edd80a.5ae0.38fb@mx.google.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/perf_event.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kernel/perf_event.c b/kernel/perf_event.c index ff86c558af4c..ac869dc78965 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -1757,7 +1757,13 @@ static u64 perf_event_read(struct perf_event *event) unsigned long flags; raw_spin_lock_irqsave(&ctx->lock, flags); - update_context_time(ctx); + /* + * may read while context is not active + * (e.g., thread is blocked), in that case + * we cannot update context time + */ + if (ctx->is_active) + update_context_time(ctx); update_event_times(event); raw_spin_unlock_irqrestore(&ctx->lock, flags); } -- cgit v1.2.3 From 49a9147eae80171bdc942c946e82cdaed3065a6f Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 9 Sep 2010 19:02:40 +0000 Subject: powerpc/perf: Fix sampling enable for PPC970 commit 9f5f9ffe50e90ed73040d2100db8bfc341cee352 upstream. The logic to distinguish marked instruction events from ordinary events on PPC970 and derivatives was flawed. The result is that instruction sampling didn't get enabled in the PMU for some marked instruction events, so they would never trigger. This fixes it by adding the appropriate break statements in the switch statement. Reported-by: David Binderman Signed-off-by: Paul Mackerras Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/ppc970-pmu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/kernel/ppc970-pmu.c b/arch/powerpc/kernel/ppc970-pmu.c index 8eff48e20dba..3fee685de4df 100644 --- a/arch/powerpc/kernel/ppc970-pmu.c +++ b/arch/powerpc/kernel/ppc970-pmu.c @@ -169,9 +169,11 @@ static int p970_marked_instr_event(u64 event) switch (unit) { case PM_VPU: mask = 0x4c; /* byte 0 bits 2,3,6 */ + break; case PM_LSU0: /* byte 2 bits 0,2,3,4,6; all of byte 1 */ mask = 0x085dff00; + break; case PM_LSU1L: mask = 0x50 << 24; /* byte 3 bits 4,6 */ break; -- cgit v1.2.3 From a02c10c18f6b7d722c2e9c0db5b92c039af81e88 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Sun, 17 Oct 2010 18:41:24 +0400 Subject: pcmcia: synclink_cs: fix information leak to userland commit 5b917a1420d3d1a9c8da49fb0090692dc9aaee86 upstream. Structure new_line is copied to userland with some padding fields unitialized. It leads to leaking of stack memory. Signed-off-by: Vasiliy Kulikov Signed-off-by: Dominik Brodowski Signed-off-by: Greg Kroah-Hartman --- drivers/char/pcmcia/synclink_cs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 308903ec8bf8..824d67c982f0 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -4132,6 +4132,8 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (cmd != SIOCWANDEV) return hdlc_ioctl(dev, ifr, cmd); + memset(&new_line, 0, size); + switch(ifr->ifr_settings.type) { case IF_GET_IFACE: /* return current sync_serial_settings */ -- cgit v1.2.3 From 19b0be98067611d07f68faf396041da6e95eb60e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 11 Oct 2010 16:36:51 +0200 Subject: sched: Drop all load weight manipulation for RT tasks commit 17bdcf949d03306b308c5fb694849cd35f119807 upstream. Load weights are for the CFS, they do not belong in the RT task. This makes all RT scheduling classes leave the CFS weights alone. This fixes a real bug as well: I noticed the following phonomena: a process elevated to SCHED_RR forks with SCHED_RESET_ON_FORK set, and the child is indeed SCHED_OTHER, and the niceval is indeed reset to 0. However the weight inserted by set_load_weight() remains at 0, giving the task insignificat priority. With this fix, the weight is reset to what the task had before being elevated to SCHED_RR/SCHED_FIFO. Cc: Lennart Poettering Signed-off-by: Linus Walleij Signed-off-by: Peter Zijlstra LKML-Reference: <1286807811-10568-1-git-send-email-linus.walleij@stericsson.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 4fa520b111d6..4992650f8de7 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1830,12 +1830,6 @@ static void dec_nr_running(struct rq *rq) static void set_load_weight(struct task_struct *p) { - if (task_has_rt_policy(p)) { - p->se.load.weight = 0; - p->se.load.inv_weight = WMULT_CONST; - return; - } - /* * SCHED_IDLE tasks get minimal weight: */ -- cgit v1.2.3 From ee6158ba96148f198a4f1b78a24770633a568b95 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Mon, 13 Sep 2010 17:47:00 -0400 Subject: sched: Fix string comparison in /proc/sched_features commit 7740191cd909b75d75685fb08a5d1f54b8a9d28b upstream. Fix incorrect handling of the following case: INTERACTIVE INTERACTIVE_SOMETHING_ELSE The comparison only checks up to each element's length. Changelog since v1: - Embellish using some Rostedtisms. [ mingo: ^^ == smaller and cleaner ] Signed-off-by: Mathieu Desnoyers Reviewed-by: Steven Rostedt Cc: Peter Zijlstra Cc: Tony Lindgren LKML-Reference: <20100913214700.GB16118@Krystal> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 4992650f8de7..05b40f80e1d3 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -721,7 +721,7 @@ sched_feat_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { char buf[64]; - char *cmp = buf; + char *cmp; int neg = 0; int i; @@ -732,6 +732,7 @@ sched_feat_write(struct file *filp, const char __user *ubuf, return -EFAULT; buf[cnt] = 0; + cmp = strstrip(buf); if (strncmp(buf, "NO_", 3) == 0) { neg = 1; @@ -739,9 +740,7 @@ sched_feat_write(struct file *filp, const char __user *ubuf, } for (i = 0; sched_feat_names[i]; i++) { - int len = strlen(sched_feat_names[i]); - - if (strncmp(cmp, sched_feat_names[i], len) == 0) { + if (strcmp(cmp, sched_feat_names[i]) == 0) { if (neg) sysctl_sched_features &= ~(1UL << i); else -- cgit v1.2.3 From 46ee0239f6fe2bd7f2db6f4ea95e9a642cf126ec Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 22 Oct 2010 14:11:26 +0100 Subject: bluetooth: Fix missing NULL check commit c19483cc5e56ac5e22dd19cf25ba210ab1537773 upstream. Fortunately this is only exploitable on very unusual hardware. [Reported a while ago but nothing happened so just fixing it] Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/bluetooth/hci_ldisc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 76a1abb8f214..283b127cea74 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -258,9 +258,16 @@ static int hci_uart_tty_open(struct tty_struct *tty) BT_DBG("tty %p", tty); + /* FIXME: This btw is bogus, nothing requires the old ldisc to clear + the pointer */ if (hu) return -EEXIST; + /* Error if the tty has no write op instead of leaving an exploitable + hole */ + if (tty->ops->write == NULL) + return -EOPNOTSUPP; + if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) { BT_ERR("Can't allocate control structure"); return -ENFILE; -- cgit v1.2.3 From 52c974f34e857dc648f013cc24f6ad4febc26040 Mon Sep 17 00:00:00 2001 From: Darren Hart Date: Sun, 17 Oct 2010 08:35:04 -0700 Subject: futex: Fix errors in nested key ref-counting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7ada876a8703f23befbb20a7465a702ee39b1704 upstream. futex_wait() is leaking key references due to futex_wait_setup() acquiring an additional reference via the queue_lock() routine. The nested key ref-counting has been masking bugs and complicating code analysis. queue_lock() is only called with a previously ref-counted key, so remove the additional ref-counting from the queue_(un)lock() functions. Also futex_wait_requeue_pi() drops one key reference too many in unqueue_me_pi(). Remove the key reference handling from unqueue_me_pi(). This was paired with a queue_lock() in futex_lock_pi(), so the count remains unchanged. Document remaining nested key ref-counting sites. Signed-off-by: Darren Hart Reported-and-tested-by: Matthieu Fertré Reported-by: Louis Rilling Cc: Peter Zijlstra Cc: Eric Dumazet Cc: John Kacur Cc: Rusty Russell LKML-Reference: <4CBB17A8.70401@linux.intel.com> Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/futex.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/kernel/futex.c b/kernel/futex.c index 6a3a5fa1526d..e328f574c97c 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -1363,7 +1363,6 @@ static inline struct futex_hash_bucket *queue_lock(struct futex_q *q) { struct futex_hash_bucket *hb; - get_futex_key_refs(&q->key); hb = hash_futex(&q->key); q->lock_ptr = &hb->lock; @@ -1375,7 +1374,6 @@ static inline void queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb) { spin_unlock(&hb->lock); - drop_futex_key_refs(&q->key); } /** @@ -1480,8 +1478,6 @@ static void unqueue_me_pi(struct futex_q *q) q->pi_state = NULL; spin_unlock(q->lock_ptr); - - drop_futex_key_refs(&q->key); } /* @@ -1812,7 +1808,10 @@ static int futex_wait(u32 __user *uaddr, int fshared, } retry: - /* Prepare to wait on uaddr. */ + /* + * Prepare to wait on uaddr. On success, holds hb lock and increments + * q.key refs. + */ ret = futex_wait_setup(uaddr, val, fshared, &q, &hb); if (ret) goto out; @@ -1822,24 +1821,23 @@ retry: /* If we were woken (and unqueued), we succeeded, whatever. */ ret = 0; + /* unqueue_me() drops q.key ref */ if (!unqueue_me(&q)) - goto out_put_key; + goto out; ret = -ETIMEDOUT; if (to && !to->task) - goto out_put_key; + goto out; /* * We expect signal_pending(current), but we might be the * victim of a spurious wakeup as well. */ - if (!signal_pending(current)) { - put_futex_key(fshared, &q.key); + if (!signal_pending(current)) goto retry; - } ret = -ERESTARTSYS; if (!abs_time) - goto out_put_key; + goto out; restart = ¤t_thread_info()->restart_block; restart->fn = futex_wait_restart; @@ -1856,8 +1854,6 @@ retry: ret = -ERESTART_RESTARTBLOCK; -out_put_key: - put_futex_key(fshared, &q.key); out: if (to) { hrtimer_cancel(&to->timer); @@ -2236,7 +2232,10 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared, q.rt_waiter = &rt_waiter; q.requeue_pi_key = &key2; - /* Prepare to wait on uaddr. */ + /* + * Prepare to wait on uaddr. On success, increments q.key (key1) ref + * count. + */ ret = futex_wait_setup(uaddr, val, fshared, &q, &hb); if (ret) goto out_key2; @@ -2254,7 +2253,9 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared, * In order for us to be here, we know our q.key == key2, and since * we took the hb->lock above, we also know that futex_requeue() has * completed and we no longer have to concern ourselves with a wakeup - * race with the atomic proxy lock acquition by the requeue code. + * race with the atomic proxy lock acquisition by the requeue code. The + * futex_requeue dropped our key1 reference and incremented our key2 + * reference count. */ /* Check if the requeue code acquired the second futex for us. */ -- cgit v1.2.3 From 28feaa47bc4f21545dce9834d9c8f90481647c1a Mon Sep 17 00:00:00 2001 From: Suresh Jayaraman Date: Fri, 17 Sep 2010 18:56:39 +0530 Subject: cifs: fix broken oplock handling commit aa91c7e4ab9b0842b7d7a7cbf8cca18b20df89b5 upstream. cifs_new_fileinfo() does not use the 'oplock' value from the callers. Instead, it sets it to REQ_OPLOCK which seems wrong. We should be using the oplock value obtained from the Server to set the inode's clientCanCacheAll or clientCanCacheRead flags. Fix this by passing oplock from the callers to cifs_new_fileinfo(). This change dates back to commit a6ce4932 (2.6.30-rc3). So, all the affected versions will need this fix. Please Cc stable once reviewed and accepted. Reviewed-by: Jeff Layton Signed-off-by: Suresh Jayaraman Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/cifsproto.h | 3 ++- fs/cifs/dir.c | 12 +++++------- fs/cifs/file.c | 4 ++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index fb6318b81509..4c54a8b3da5b 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -104,7 +104,8 @@ extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file, - struct vfsmount *mnt, unsigned int oflags); + struct vfsmount *mnt, unsigned int oflags, + __u32 oplock); extern int cifs_posix_open(char *full_path, struct inode **pinode, struct super_block *sb, int mode, int oflags, diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index e7ae78b66fa1..9c338780fbab 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -138,9 +138,9 @@ cifs_bp_rename_retry: */ struct cifsFileInfo * cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, - struct file *file, struct vfsmount *mnt, unsigned int oflags) + struct file *file, struct vfsmount *mnt, unsigned int oflags, + __u32 oplock) { - int oplock = 0; struct cifsFileInfo *pCifsFile; struct cifsInodeInfo *pCifsInode; struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb); @@ -149,9 +149,6 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, if (pCifsFile == NULL) return pCifsFile; - if (oplockEnabled) - oplock = REQ_OPLOCK; - pCifsFile->netfid = fileHandle; pCifsFile->pid = current->tgid; pCifsFile->pInode = igrab(newinode); @@ -476,7 +473,7 @@ cifs_create_set_dentry: } pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp, - nd->path.mnt, oflags); + nd->path.mnt, oflags, oplock); if (pfile_info == NULL) { fput(filp); CIFSSMBClose(xid, tcon, fileHandle); @@ -738,7 +735,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, cfile = cifs_new_fileinfo(newInode, fileHandle, filp, nd->path.mnt, - nd->intent.open.flags); + nd->intent.open.flags, + oplock); if (cfile == NULL) { fput(filp); CIFSSMBClose(xid, pTcon, fileHandle); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 409e4f523e61..de2e6c42e243 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -277,7 +277,7 @@ int cifs_open(struct inode *inode, struct file *file) pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt, - oflags); + oflags, oplock); if (pCifsFile == NULL) { CIFSSMBClose(xid, tcon, netfid); rc = -ENOMEM; @@ -367,7 +367,7 @@ int cifs_open(struct inode *inode, struct file *file) goto out; pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt, - file->f_flags); + file->f_flags, oplock); if (pCifsFile == NULL) { rc = -ENOMEM; goto out; -- cgit v1.2.3 From 4fc910677fa95f03bd8431d21766ba9d7d967fa0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 15 Oct 2010 11:00:08 +0200 Subject: libahci: fix result_tf handling after an ATA PIO data-in command commit 6ad601955315b010a117306b994f2204fae85fdc upstream. ATA devices don't send D2H Reg FIS after an successful ATA PIO data-in command. The host is supposed to take the TF and E_Status of the preceding PIO Setup FIS. Update ahci_qc_fill_rtf() such that it takes TF + E_Status from PIO Setup FIS after a successful ATA PIO data-in command. Without this patch, result_tf for such a command is filled with the content of the previous D2H Reg FIS which belongs to a previous command, which can make the command incorrectly seen as failed. * Patch updated to grab the whole TF + E_Status from PIO Setup FIS instead of just E_Status as suggested by Robert Hancock. Signed-off-by: Tejun Heo Reported-by: Mark Lord Cc: Robert Hancock Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/ahci.h | 1 + drivers/ata/libahci.c | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 88aa888a7e14..22a20e856343 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -72,6 +72,7 @@ enum { AHCI_CMD_RESET = (1 << 8), AHCI_CMD_CLR_BUSY = (1 << 10), + RX_FIS_PIO_SETUP = 0x20, /* offset of PIO Setup FIS data */ RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */ RX_FIS_SDB = 0x58, /* offset of SDB FIS data */ RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */ diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index b765a01cd272..b5aecd0c7245 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1824,12 +1824,24 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc) { struct ahci_port_priv *pp = qc->ap->private_data; - u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; + u8 *rx_fis = pp->rx_fis; if (pp->fbs_enabled) - d2h_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ; + rx_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ; + + /* + * After a successful execution of an ATA PIO data-in command, + * the device doesn't send D2H Reg FIS to update the TF and + * the host should take TF and E_Status from the preceding PIO + * Setup FIS. + */ + if (qc->tf.protocol == ATA_PROT_PIO && qc->dma_dir == DMA_FROM_DEVICE && + !(qc->flags & ATA_QCFLAG_FAILED)) { + ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf); + qc->result_tf.command = (rx_fis + RX_FIS_PIO_SETUP)[15]; + } else + ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf); - ata_tf_from_fis(d2h_fis, &qc->result_tf); return true; } -- cgit v1.2.3 From db11393d79684afc15b3d3d52a1664171180c350 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 23 Oct 2010 23:25:53 -0400 Subject: intel_idle: do not use the LAPIC timer for ATOM C2 commit c25d29952b2a8c9aaf00e081c9162a0e383030cd upstream. If we use the LAPIC timer during ATOM C2 on some nvidia chisets, the system stalls. https://bugzilla.kernel.org/show_bug.cgi?id=21032 Signed-off-by: Len Brown Cc: Tom Gundersen Signed-off-by: Greg Kroah-Hartman --- drivers/idle/intel_idle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 54f0fb4cd5d2..ae48da953834 100755 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -308,7 +308,7 @@ static int intel_idle_probe(void) break; case 0x1C: /* 28 - Atom Processor */ - lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */ + lapic_timer_reliable_states = (1 << 1); /* C1 */ cpuidle_state_table = atom_cstates; choose_substate = choose_zero_substate; break; -- cgit v1.2.3 From ff7d23175ecbff5666f7a9f26dfe1f4334e04377 Mon Sep 17 00:00:00 2001 From: Cliff Wickman Date: Thu, 16 Sep 2010 11:44:02 -0500 Subject: mm, x86: Saving vmcore with non-lazy freeing of vmas commit 3ee48b6af49cf534ca2f481ecc484b156a41451d upstream. During the reading of /proc/vmcore the kernel is doing ioremap()/iounmap() repeatedly. And the buildup of un-flushed vm_area_struct's is causing a great deal of overhead. (rb_next() is chewing up most of that time). This solution is to provide function set_iounmap_nonlazy(). It causes a subsequent call to iounmap() to immediately purge the vma area (with try_purge_vmap_area_lazy()). With this patch we have seen the time for writing a 250MB compressed dump drop from 71 seconds to 44 seconds. Signed-off-by: Cliff Wickman Cc: Andrew Morton Cc: kexec@lists.infradead.org LKML-Reference: Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/io.h | 1 + arch/x86/kernel/crash_dump_64.c | 1 + mm/vmalloc.c | 9 +++++++++ 3 files changed, 11 insertions(+) diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 30a3e9776123..6a45ec41ec26 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -206,6 +206,7 @@ static inline void __iomem *ioremap(resource_size_t offset, unsigned long size) extern void iounmap(volatile void __iomem *addr); +extern void set_iounmap_nonlazy(void); #ifdef __KERNEL__ diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c index 045b36cada65..ce96a6b575b7 100644 --- a/arch/x86/kernel/crash_dump_64.c +++ b/arch/x86/kernel/crash_dump_64.c @@ -46,6 +46,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, } else memcpy(buf, vaddr + offset, csize); + set_iounmap_nonlazy(); iounmap(vaddr); return csize; } diff --git a/mm/vmalloc.c b/mm/vmalloc.c index ae007462b7f6..20a402ce7bd2 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -512,6 +512,15 @@ static atomic_t vmap_lazy_nr = ATOMIC_INIT(0); /* for per-CPU blocks */ static void purge_fragmented_blocks_allcpus(void); +/* + * called before a call to iounmap() if the caller wants vm_area_struct's + * immediately freed. + */ +void set_iounmap_nonlazy(void) +{ + atomic_set(&vmap_lazy_nr, lazy_max_pages()+1); +} + /* * Purges all lazily-freed vmap areas. * -- cgit v1.2.3 From 8298c02ab797b1e1ac2671a49038d3f8f31db20b Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 6 Sep 2010 15:14:17 +0200 Subject: x86, cpu: Fix renamed, not-yet-shipping AMD CPUID feature bit commit 7ef8aa72ab176e0288f363d1247079732c5d5792 upstream. The AMD SSE5 feature set as-it has been replaced by some extensions to the AVX instruction set. Thus the bit formerly advertised as SSE5 is re-used for one of these extensions (XOP). Although this changes the /proc/cpuinfo output, it is not user visible, as there are no CPUs (yet) having this feature. To avoid confusion this should be added to the stable series, too. Signed-off-by: Andre Przywara LKML-Reference: <1283778860-26843-2-git-send-email-andre.przywara@amd.com> Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/cpufeature.h | 2 +- arch/x86/kvm/x86.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 468145914389..14e0ee1b53f6 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -150,7 +150,7 @@ #define X86_FEATURE_3DNOWPREFETCH (6*32+ 8) /* 3DNow prefetch instructions */ #define X86_FEATURE_OSVW (6*32+ 9) /* OS Visible Workaround */ #define X86_FEATURE_IBS (6*32+10) /* Instruction Based Sampling */ -#define X86_FEATURE_SSE5 (6*32+11) /* SSE-5 */ +#define X86_FEATURE_XOP (6*32+11) /* extended AVX instructions */ #define X86_FEATURE_SKINIT (6*32+12) /* SKINIT/STGI instructions */ #define X86_FEATURE_WDT (6*32+13) /* Watchdog timer */ #define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */ diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index fd2268838ca2..7b32ddb05a54 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1912,7 +1912,7 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, const u32 kvm_supported_word6_x86_features = F(LAHF_LM) | F(CMP_LEGACY) | F(SVM) | 0 /* ExtApicSpace */ | F(CR8_LEGACY) | F(ABM) | F(SSE4A) | F(MISALIGNSSE) | - F(3DNOWPREFETCH) | 0 /* OSVW */ | 0 /* IBS */ | F(SSE5) | + F(3DNOWPREFETCH) | 0 /* OSVW */ | 0 /* IBS */ | F(XOP) | 0 /* SKINIT */ | 0 /* WDT */; /* all calls to cpuid_count() should be made on the same cpu */ -- cgit v1.2.3 From 644b2192d251acb3a44c5cf8a209ff0c6217716c Mon Sep 17 00:00:00 2001 From: Alok Kataria Date: Mon, 11 Oct 2010 14:37:08 -0700 Subject: x86, kexec: Make sure to stop all CPUs before exiting the kernel commit 76fac077db6b34e2c6383a7b4f3f4f7b7d06d8ce upstream. x86 smp_ops now has a new op, stop_other_cpus which takes a parameter "wait" this allows the caller to specify if it wants to stop until all the cpus have processed the stop IPI. This is required specifically for the kexec case where we should wait for all the cpus to be stopped before starting the new kernel. We now wait for the cpus to stop in all cases except for panic/kdump where we expect things to be broken and we are doing our best to make things work anyway. This patch fixes a legitimate regression, which was introduced during 2.6.30, by commit id 4ef702c10b5df18ab04921fc252c26421d4d6c75. Signed-off-by: Alok N Kataria LKML-Reference: <1286833028.1372.20.camel@ank32.eng.vmware.com> Cc: Eric W. Biederman Cc: Jeremy Fitzhardinge Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/smp.h | 9 +++++++-- arch/x86/kernel/reboot.c | 2 +- arch/x86/kernel/smp.c | 15 +++++++++------ arch/x86/xen/enlighten.c | 2 +- arch/x86/xen/smp.c | 6 +++--- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 4cfc90824068..4c2f63c7fc1b 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -50,7 +50,7 @@ struct smp_ops { void (*smp_prepare_cpus)(unsigned max_cpus); void (*smp_cpus_done)(unsigned max_cpus); - void (*smp_send_stop)(void); + void (*stop_other_cpus)(int wait); void (*smp_send_reschedule)(int cpu); int (*cpu_up)(unsigned cpu); @@ -73,7 +73,12 @@ extern struct smp_ops smp_ops; static inline void smp_send_stop(void) { - smp_ops.smp_send_stop(); + smp_ops.stop_other_cpus(0); +} + +static inline void stop_other_cpus(void) +{ + smp_ops.stop_other_cpus(1); } static inline void smp_prepare_boot_cpu(void) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index e3af342fe83a..76a0d715a031 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -641,7 +641,7 @@ void native_machine_shutdown(void) /* O.K Now that I'm on the appropriate processor, * stop all of the others. */ - smp_send_stop(); + stop_other_cpus(); #endif lapic_shutdown(); diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index d801210945d6..513deac7228d 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -159,10 +159,10 @@ asmlinkage void smp_reboot_interrupt(void) irq_exit(); } -static void native_smp_send_stop(void) +static void native_stop_other_cpus(int wait) { unsigned long flags; - unsigned long wait; + unsigned long timeout; if (reboot_force) return; @@ -179,9 +179,12 @@ static void native_smp_send_stop(void) if (num_online_cpus() > 1) { apic->send_IPI_allbutself(REBOOT_VECTOR); - /* Don't wait longer than a second */ - wait = USEC_PER_SEC; - while (num_online_cpus() > 1 && wait--) + /* + * Don't wait longer than a second if the caller + * didn't ask us to wait. + */ + timeout = USEC_PER_SEC; + while (num_online_cpus() > 1 && (wait || timeout--)) udelay(1); } @@ -227,7 +230,7 @@ struct smp_ops smp_ops = { .smp_prepare_cpus = native_smp_prepare_cpus, .smp_cpus_done = native_smp_cpus_done, - .smp_send_stop = native_smp_send_stop, + .stop_other_cpus = native_stop_other_cpus, .smp_send_reschedule = native_smp_send_reschedule, .cpu_up = native_cpu_up, diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 27dff06d9793..4d32089d093b 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1001,7 +1001,7 @@ static void xen_reboot(int reason) struct sched_shutdown r = { .reason = reason }; #ifdef CONFIG_SMP - smp_send_stop(); + stop_other_cpus(); #endif if (HYPERVISOR_sched_op(SCHEDOP_shutdown, &r)) diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index a29693fd3138..d2dfbf500fc8 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -398,9 +398,9 @@ static void stop_self(void *v) BUG(); } -static void xen_smp_send_stop(void) +static void xen_stop_other_cpus(int wait) { - smp_call_function(stop_self, NULL, 0); + smp_call_function(stop_self, NULL, wait); } static void xen_smp_send_reschedule(int cpu) @@ -468,7 +468,7 @@ static const struct smp_ops xen_smp_ops __initdata = { .cpu_disable = xen_cpu_disable, .play_dead = xen_play_dead, - .smp_send_stop = xen_smp_send_stop, + .stop_other_cpus = xen_stop_other_cpus, .smp_send_reschedule = xen_smp_send_reschedule, .send_call_func_ipi = xen_smp_send_call_function_ipi, -- cgit v1.2.3 From ce04bd41d98be5b9771ba5c50e84813d986637fc Mon Sep 17 00:00:00 2001 From: Paul Fox Date: Fri, 1 Oct 2010 18:17:19 +0100 Subject: x86, olpc: Don't retry EC commands forever commit 286e5b97eb22baab9d9a41ca76c6b933a484252c upstream. Avoids a potential infinite loop. It was observed once, during an EC hacking/debugging session - not in regular operation. Signed-off-by: Daniel Drake Cc: dilinger@queued.net Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/olpc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/olpc.c b/arch/x86/kernel/olpc.c index 8297160c41b3..a23b38252b85 100644 --- a/arch/x86/kernel/olpc.c +++ b/arch/x86/kernel/olpc.c @@ -117,6 +117,7 @@ int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen, unsigned long flags; int ret = -EIO; int i; + int restarts = 0; spin_lock_irqsave(&ec_lock, flags); @@ -173,7 +174,9 @@ restart: if (wait_on_obf(0x6c, 1)) { printk(KERN_ERR "olpc-ec: timeout waiting for" " EC to provide data!\n"); - goto restart; + if (restarts++ < 10) + goto restart; + goto err; } outbuf[i] = inb(0x68); printk(KERN_DEBUG "olpc-ec: received 0x%x\n", -- cgit v1.2.3 From 548bf3583a67e0af7660cfe08674d9b860ec633a Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Thu, 30 Sep 2010 14:32:35 +0200 Subject: x86, mtrr: Assume SYS_CFG[Tom2ForceMemTypeWB] exists on all future AMD CPUs commit 3fdbf004c1706480a7c7fac3c9d836fa6df20d7d upstream. Instead of adapting the CPU family check in amd_special_default_mtrr() for each new CPU family assume that all new AMD CPUs support the necessary bits in SYS_CFG MSR. Tom2Enabled is architectural (defined in APM Vol.2). Tom2ForceMemTypeWB is defined in all BKDGs starting with K8 NPT. In pre K8-NPT BKDG this bit is reserved (read as zero). W/o this adaption Linux would unnecessarily complain about bad MTRR settings on every new AMD CPU family, e.g. [ 0.000000] WARNING: BIOS bug: CPU MTRRs don't cover all of memory, losing 4863MB of RAM. Signed-off-by: Andreas Herrmann LKML-Reference: <20100930123235.GB20545@loge.amd.com> Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mtrr/cleanup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/mtrr/cleanup.c b/arch/x86/kernel/cpu/mtrr/cleanup.c index 06130b52f012..a67038401129 100644 --- a/arch/x86/kernel/cpu/mtrr/cleanup.c +++ b/arch/x86/kernel/cpu/mtrr/cleanup.c @@ -827,7 +827,7 @@ int __init amd_special_default_mtrr(void) if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) return 0; - if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11) + if (boot_cpu_data.x86 < 0xf) return 0; /* In case some hypervisor doesn't pass SYSCFG through: */ if (rdmsr_safe(MSR_K8_SYSCFG, &l, &h) < 0) -- cgit v1.2.3 From 7925978534b7180dac82c87eb6a5bbe96654ba75 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Fri, 27 Aug 2010 11:09:48 -0700 Subject: x86, intr-remap: Set redirection hint in the IRTE commit 75e3cfbed6f71a8f151dc6e413b6ce3c390030cb upstream. Currently the redirection hint in the interrupt-remapping table entry is set to 0, which means the remapped interrupt is directed to the processors listed in the destination. So in logical flat mode in the presence of intr-remapping, this results in a single interrupt multi-casted to multiple cpu's as specified by the destination bit mask. But what we really want is to send that interrupt to one of the cpus based on the lowest priority delivery mode. Set the redirection hint in the IRTE to '1' to indicate that we want the remapped interrupt to be directed to only one of the processors listed in the destination. This fixes the issue of same interrupt getting delivered to multiple cpu's in the logical flat mode in the presence of interrupt-remapping. While there is no functional issue observed with this behavior, this will impact performance of such configurations (<=8 cpu's using logical flat mode in the presence of interrupt-remapping) Signed-off-by: Suresh Siddha LKML-Reference: <20100827181049.013051492@sbsiddha-MOBL3.sc.intel.com> Cc: Weidong Han Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/apic/io_apic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 5c5b8f3dddb5..ad1515dbc5ef 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1397,6 +1397,7 @@ int setup_ioapic_entry(int apic_id, int irq, irte.dlvry_mode = apic->irq_delivery_mode; irte.vector = vector; irte.dest_id = IRTE_DEST(destination); + irte.redir_hint = 1; /* Set source-id of interrupt request */ set_ioapic_sid(&irte, apic_id); @@ -3348,6 +3349,7 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, irte.dlvry_mode = apic->irq_delivery_mode; irte.vector = cfg->vector; irte.dest_id = IRTE_DEST(dest); + irte.redir_hint = 1; /* Set source-id of interrupt request */ if (pdev) -- cgit v1.2.3 From d59159c62f66de966c601c1b7174e798e4a3d0d4 Mon Sep 17 00:00:00 2001 From: Cliff Wickman Date: Wed, 8 Sep 2010 10:14:27 -0500 Subject: x86, kdump: Change copy_oldmem_page() to use cached addressing commit 37a2f9f30a360fb03522d15c85c78265ccd80287 upstream. The copy of /proc/vmcore to a user buffer proceeds much faster if the kernel addresses memory as cached. With this patch we have seen an increase in transfer rate from less than 15MB/s to 80-460MB/s, depending on size of the transfer. This makes a big difference in time needed to save a system dump. Signed-off-by: Cliff Wickman Acked-by: "Eric W. Biederman" Cc: kexec@lists.infradead.org LKML-Reference: Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/crash_dump_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c index ce96a6b575b7..994828899e09 100644 --- a/arch/x86/kernel/crash_dump_64.c +++ b/arch/x86/kernel/crash_dump_64.c @@ -34,7 +34,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, if (!csize) return 0; - vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE); + vaddr = ioremap_cache(pfn << PAGE_SHIFT, PAGE_SIZE); if (!vaddr) return -ENOMEM; -- cgit v1.2.3 From b78891dfa05b86e74efdc4e7ed47f279ae96aa4b Mon Sep 17 00:00:00 2001 From: Bart Oldeman Date: Thu, 23 Sep 2010 13:16:58 -0400 Subject: x86, vm86: Fix preemption bug for int1 debug and int3 breakpoint handlers. commit 6554287b1de0448f1e02e200d02b43914e997d15 upstream. Impact: fix kernel bug such as: BUG: scheduling while atomic: dosemu.bin/19680/0x00000004 See also Ubuntu bug 455067 at https://bugs.launchpad.net/ubuntu/+source/linux/+bug/455067 Commits 4915a35e35a037254550a2ba9f367a812bc37d40 ("Use preempt_conditional_sti/cli in do_int3, like on x86_64.") and 3d2a71a596bd9c761c8487a2178e95f8a61da083 ("x86, traps: converge do_debug handlers") started disabling preemption in int1 and int3 handlers on i386. The problem with vm86 is that the call to handle_vm86_trap() may jump straight to entry_32.S and never returns so preempt is never enabled again, and there is an imbalance in the preempt count. Commit be716615fe596ee117292dc615e95f707fb67fd1 ("x86, vm86: fix preemption bug"), which was later (accidentally?) reverted by commit 08d68323d1f0c34452e614263b212ca556dae47f ("hw-breakpoints: modifying generic debug exception to use thread-specific debug registers") fixed the problem for debug exceptions but not for breakpoints. There are three solutions to this problem. 1. Reenable preemption before calling handle_vm86_trap(). This was the approach that was later reverted. 2. Do not disable preemption for i386 in breakpoint and debug handlers. This was the situation before October 2008. As far as I understand preemption only needs to be disabled on x86_64 because a seperate stack is used, but it's nice to have things work the same way on i386 and x86_64. 3. Let handle_vm86_trap() return instead of jumping to assembly code. By setting a flag in _TIF_WORK_MASK, either TIF_IRET or TIF_NOTIFY_RESUME, the code in entry_32.S is instructed to return to 32 bit mode from V86 mode. The logic in entry_32.S was already present to handle signals. (I chose TIF_IRET because it's slightly more efficient in do_notify_resume() in signal.c, but in fact TIF_IRET can probably be replaced by TIF_NOTIFY_RESUME everywhere.) I'm submitting approach 3, because I believe it is the most elegant and prevents future confusion. Still, an obvious preempt_conditional_cli(regs); is necessary in traps.c to correct the bug. [ hpa: This is technically a regression, but because: 1. the regression is so old, 2. the patch seems relatively high risk, justifying more testing, and 3. we're late in the 2.6.36-rc cycle, I'm queuing it up for the 2.6.37 merge window. It might, however, justify as a -stable backport at a latter time, hence Cc: stable. ] Signed-off-by: Bart Oldeman LKML-Reference: Cc: Frederic Weisbecker Cc: K.Prasad Cc: Alan Stern Cc: Alexander van Heukelum Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/traps.c | 1 + arch/x86/kernel/vm86_32.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 725ef4d17cd5..4d0f3ed34c41 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -568,6 +568,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) if (regs->flags & X86_VM_MASK) { handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1); + preempt_conditional_cli(regs); return; } diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index 5ffb5622f793..61fb98519622 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -551,8 +551,14 @@ cannot_handle: int handle_vm86_trap(struct kernel_vm86_regs *regs, long error_code, int trapno) { if (VMPI.is_vm86pus) { - if ((trapno == 3) || (trapno == 1)) - return_to_32bit(regs, VM86_TRAP + (trapno << 8)); + if ((trapno == 3) || (trapno == 1)) { + KVM86->regs32->ax = VM86_TRAP + (trapno << 8); + /* setting this flag forces the code in entry_32.S to + call save_v86_state() and change the stack pointer + to KVM86->regs32 */ + set_thread_flag(TIF_IRET); + return 0; + } do_int(regs, trapno, (unsigned char __user *) (regs->pt.ss << 4), SP(regs)); return 0; } -- cgit v1.2.3 From c0b67df56563d6e27b111fcf8cc8cf694ec4b87c Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 10 Sep 2010 17:31:06 +0200 Subject: KVM: X86: Report SVM bit to userspace only when supported commit 4c62a2dc92518c5adf434df8e5c2283c6762672a upstream. This patch fixes a bug in KVM where it _always_ reports the support of the SVM feature to userspace. But KVM only supports SVM on AMD hardware and only when it is enabled in the kernel module. This patch fixes the wrong reporting. Signed-off-by: Joerg Roedel Signed-off-by: Avi Kivity Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/svm.c | 4 ++++ arch/x86/kvm/x86.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 93730fe9f7e9..965a7fa071b6 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -3253,6 +3253,10 @@ static void svm_cpuid_update(struct kvm_vcpu *vcpu) static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry) { switch (func) { + case 0x80000001: + if (nested) + entry->ecx |= (1 << 2); /* Set SVM bit */ + break; case 0x8000000A: entry->eax = 1; /* SVM revision 1 */ entry->ebx = 8; /* Lets support 8 ASIDs in case we add proper diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 7b32ddb05a54..be9251193d2a 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1910,7 +1910,7 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, 0 /* Reserved, XSAVE, OSXSAVE */; /* cpuid 0x80000001.ecx */ const u32 kvm_supported_word6_x86_features = - F(LAHF_LM) | F(CMP_LEGACY) | F(SVM) | 0 /* ExtApicSpace */ | + F(LAHF_LM) | F(CMP_LEGACY) | 0 /*SVM*/ | 0 /* ExtApicSpace */ | F(CR8_LEGACY) | F(ABM) | F(SSE4A) | F(MISALIGNSSE) | F(3DNOWPREFETCH) | 0 /* OSVW */ | 0 /* IBS */ | F(XOP) | 0 /* SKINIT */ | 0 /* WDT */; -- cgit v1.2.3 From fb84c60fcdbcd33c162f2503aae1ac688ee2f4d2 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 2 Sep 2010 17:29:46 +0200 Subject: KVM: SVM: Restore correct registers after sel_cr0 intercept emulation commit cda0008299a06f0d7218c6037c3c02d7a865e954 upstream. This patch implements restoring of the correct rip, rsp, and rax after the svm emulation in KVM injected a selective_cr0 write intercept into the guest hypervisor. The problem was that the vmexit is emulated in the instruction emulation which later commits the registers right after the write-cr0 instruction. So the l1 guest will continue to run with the l2 rip, rsp and rax resulting in unpredictable behavior. This patch is not the final word, it is just an easy patch to fix the issue. The real fix will be done when the instruction emulator is made aware of nested virtualization. Until this is done this patch fixes the issue and provides an easy way to fix this in -stable too. Signed-off-by: Joerg Roedel Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/svm.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 965a7fa071b6..02a5603695e3 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -87,6 +87,14 @@ struct nested_state { /* A VMEXIT is required but not yet emulated */ bool exit_required; + /* + * If we vmexit during an instruction emulation we need this to restore + * the l1 guest rip after the emulation + */ + unsigned long vmexit_rip; + unsigned long vmexit_rsp; + unsigned long vmexit_rax; + /* cache for intercepts of the guest */ u16 intercept_cr_read; u16 intercept_cr_write; @@ -1201,8 +1209,12 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) if (old == new) { /* cr0 write with ts and mp unchanged */ svm->vmcb->control.exit_code = SVM_EXIT_CR0_SEL_WRITE; - if (nested_svm_exit_handled(svm) == NESTED_EXIT_DONE) + if (nested_svm_exit_handled(svm) == NESTED_EXIT_DONE) { + svm->nested.vmexit_rip = kvm_rip_read(vcpu); + svm->nested.vmexit_rsp = kvm_register_read(vcpu, VCPU_REGS_RSP); + svm->nested.vmexit_rax = kvm_register_read(vcpu, VCPU_REGS_RAX); return; + } } } @@ -2398,6 +2410,23 @@ static int emulate_on_interception(struct vcpu_svm *svm) return 1; } +static int cr0_write_interception(struct vcpu_svm *svm) +{ + struct kvm_vcpu *vcpu = &svm->vcpu; + int r; + + r = emulate_instruction(&svm->vcpu, 0, 0, 0); + + if (svm->nested.vmexit_rip) { + kvm_register_write(vcpu, VCPU_REGS_RIP, svm->nested.vmexit_rip); + kvm_register_write(vcpu, VCPU_REGS_RSP, svm->nested.vmexit_rsp); + kvm_register_write(vcpu, VCPU_REGS_RAX, svm->nested.vmexit_rax); + svm->nested.vmexit_rip = 0; + } + + return r == EMULATE_DONE; +} + static int cr8_write_interception(struct vcpu_svm *svm) { struct kvm_run *kvm_run = svm->vcpu.run; @@ -2671,7 +2700,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm) = { [SVM_EXIT_READ_CR4] = emulate_on_interception, [SVM_EXIT_READ_CR8] = emulate_on_interception, [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception, - [SVM_EXIT_WRITE_CR0] = emulate_on_interception, + [SVM_EXIT_WRITE_CR0] = cr0_write_interception, [SVM_EXIT_WRITE_CR3] = emulate_on_interception, [SVM_EXIT_WRITE_CR4] = emulate_on_interception, [SVM_EXIT_WRITE_CR8] = cr8_write_interception, -- cgit v1.2.3 From 5ed216a908c5273995b2c65c14639c8b3448b065 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Oct 2010 10:49:10 +0200 Subject: USB: mct_u232: fix broken close commit 92ca0dc5ee022e4c0e488177e1d8865a0778c6c2 upstream. Fix regression introduced by commit f26788da3b342099d2b02d99ba1cb7f154d6ef7b (USB: serial: refactor generic close) which broke driver close(). This driver uses non-standard semantics for the read urb which makes the generic close function fail to kill it (the read urb is actually an interrupt urb and therefore bulk_in size is zero). Reported-by: Eric Shattow "Eprecocious" Tested-by: Eric Shattow "Eprecocious" Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mct_u232.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 7aa01b95b1d4..2849f8c32015 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -549,9 +549,12 @@ static void mct_u232_close(struct usb_serial_port *port) { dbg("%s port %d", __func__, port->number); - usb_serial_generic_close(port); - if (port->serial->dev) + if (port->serial->dev) { + /* shutdown our urbs */ + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); usb_kill_urb(port->interrupt_in_urb); + } } /* mct_u232_close */ -- cgit v1.2.3 From ea8ef5f07004708a74cf6c29a43b41db3a58dec8 Mon Sep 17 00:00:00 2001 From: Nicolas Kaiser Date: Thu, 21 Oct 2010 14:56:00 +0200 Subject: pipe: fix failure to return error code on ->confirm() commit e5953cbdff26f7cbae7eff30cd9b18c4e19b7594 upstream. The arguments were transposed, we want to assign the error code to 'ret', which is being returned. Signed-off-by: Nicolas Kaiser Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- fs/pipe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/pipe.c b/fs/pipe.c index 279eef96c51c..37eb1ebeaa90 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -382,7 +382,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, error = ops->confirm(pipe, buf); if (error) { if (!ret) - error = ret; + ret = error; break; } -- cgit v1.2.3 From 7522ac94eb35ae9cf42540279b3e36344a5db52a Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 22 Aug 2010 22:41:33 +0200 Subject: p54usb: fix off-by-one on !CONFIG_PM commit 11791a6f7534906b4a01ffb54ba0b02ca39398ef upstream. The ISL3887 chip needs a USB reset, whenever the usb-frontend module "p54usb" is reloaded. This patch fixes an off-by-one bug, if the user is running a kernel without the CONFIG_PM option set and for some reason (e.g.: compat-wireless) wants to switch between different p54usb modules. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/p54/p54usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 73073259f508..98152e2c27dc 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -930,8 +930,8 @@ static int __devinit p54u_probe(struct usb_interface *intf, #ifdef CONFIG_PM /* ISL3887 needs a full reset on resume */ udev->reset_resume = 1; +#endif /* CONFIG_PM */ err = p54u_device_reset(dev); -#endif priv->hw_type = P54U_3887; dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr); -- cgit v1.2.3 From 4ffa3ba40ebed6a0fe70a19cb90addd20a5d57e1 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 1 Oct 2010 22:01:24 +0200 Subject: p54usb: add five more USBIDs commit 1a92795dac419128eb511dce30a6aad672064b88 upstream. Source: http://www.wikidevi.com/wiki/Intersil/p54/usb/windows Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/p54/p54usb.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 98152e2c27dc..1214afe5858c 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -33,8 +33,17 @@ MODULE_ALIAS("prism54usb"); MODULE_FIRMWARE("isl3886usb"); MODULE_FIRMWARE("isl3887usb"); +/* + * Note: + * + * Always update our wiki's device list (located at: + * http://wireless.kernel.org/en/users/Drivers/p54/devices ), + * whenever you add a new device. + */ + static struct usb_device_id p54u_table[] __devinitdata = { /* Version 1 devices (pci chip + net2280) */ + {USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */ {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ {USB_DEVICE(0x06b9, 0x0120)}, /* Thomson SpeedTouch 120g */ {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ @@ -47,7 +56,9 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */ {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */ {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */ + {USB_DEVICE(0x107b, 0x55f2)}, /* Gateway WGU-210 (Gemtek) */ {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */ + {USB_DEVICE(0x1630, 0x0005)}, /* 2Wire 802.11g USB (v1) / Z-Com */ {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */ {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */ {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */ @@ -60,6 +71,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */ {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */ {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */ + {USB_DEVICE(0x06a9, 0x000e)}, /* Westell 802.11g USB (A90-211WG-01) */ {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ @@ -79,6 +91,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */ {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ + {USB_DEVICE(0x1668, 0x1050)}, /* Actiontec 802UIG-1 */ {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ {USB_DEVICE(0x413c, 0x5513)}, /* Dell WLA3310 USB Wireless Adapter */ {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */ -- cgit v1.2.3 From 185de9185eafc0f7304a977d1f19c491447879e1 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 15 Oct 2010 15:00:06 +0200 Subject: drivers/net/wireless/p54/eeprom.c: Return -ENOMEM on memory allocation failure commit 0d91f22b75347d9503b17a42b6c74d3f7750acd6 upstream. In this code, 0 is returned on memory allocation failure, even though other failures return -ENOMEM or other similar values. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression ret; expression x,e1,e2,e3; @@ ret = 0 ... when != ret = e1 *x = \(kmalloc\|kcalloc\|kzalloc\)(...) ... when != ret = e2 if (x == NULL) { ... when != ret = e3 return ret; } // Signed-off-by: Julia Lawall Acked-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/p54/eeprom.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index 187e263b045a..53d0f201c942 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c @@ -262,8 +262,10 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) list->max_entries = max_channel_num; list->channels = kzalloc(sizeof(struct p54_channel_entry) * max_channel_num, GFP_KERNEL); - if (!list->channels) + if (!list->channels) { + ret = -ENOMEM; goto free; + } for (i = 0; i < max_channel_num; i++) { if (i < priv->iq_autocal_len) { -- cgit v1.2.3 From 8f8ed8cbe2cdc19e6978c031d8d75870d7fec50f Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 8 Sep 2010 13:48:44 +0300 Subject: usb gadget: composite: prevent OOPS for non-standard control request commit 5c836e4d583701a5eecb288b5f131da39115f5ec upstream. The composite gadget will OOPS if the host sends a control request targetted to an interface of an un-configured composite device. This patch prevents this. The OOPS was observed during WHQL USB CV tests. With this patch, the device STALLs as per requirement. Failing test case: From host do the following. I used libusb-1.0 1) Set configuration to zero. libusb_control_transfer(device_handle, 0, /* standard OUT */ 0x9, /* setConfiguration */ 0, 0, NULL, 0, 0); 2) Query current configuratioan. libusb_control_transfer(device_handle, 0x80, /* standard IN*/ 0x8, /* getConfiguration */ 0, 0, data, 1, 0); 3) Send the non-standard ctrl transfer targetted to interface libusb_control_transfer(device_handle, 0x81, /* standard IN to interface*/ 0x6, /* getDescriptor */ 0x2300, 0, data, 0x12, 0); Signed-off-by: Roger Quadros Cc: David Brownell Cc: Michal Nazarewicz Cc: Robert Lukassen Cc: Kyungmin Park Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/composite.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 391d169f8d07..4b02b320e61c 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -838,7 +838,8 @@ unknown: */ switch (ctrl->bRequestType & USB_RECIP_MASK) { case USB_RECIP_INTERFACE: - f = cdev->config->interface[intf]; + if (cdev->config) + f = cdev->config->interface[intf]; break; case USB_RECIP_ENDPOINT: -- cgit v1.2.3 From 70cb495a276ea4f051e9d8b6edee1190c54a75d1 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 12 Aug 2010 17:43:45 +0200 Subject: USB: gadget: g_ffs: fixed vendor and product ID commit ba0534be935d7b24e5fdd6f82c443ee75abc9149 upstream. This patch fixes the vendor and product ID the gadget uses by replacing the temporary IDs that were used during development (which should never get into mainline) with proper IDs. Signed-off-by: Michal Nazarewicz Signed-off-by: Kyungmin Park Signed-off-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/g_ffs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index d1af253a9105..bc433226dc22 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -52,8 +52,8 @@ MODULE_AUTHOR("Michal Nazarewicz"); MODULE_LICENSE("GPL"); -static unsigned short gfs_vendor_id = 0x0525; /* XXX NetChip */ -static unsigned short gfs_product_id = 0xa4ac; /* XXX */ +static unsigned short gfs_vendor_id = 0x1d6b; /* Linux Foundation */ +static unsigned short gfs_product_id = 0x0105; /* FunctionFS Gadget */ static struct usb_device_descriptor gfs_dev_desc = { .bLength = sizeof gfs_dev_desc, -- cgit v1.2.3 From 5aaade9e6a6f829ae8d94e5e0b04897ae9d4535e Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 12 Aug 2010 17:43:44 +0200 Subject: USB: gadget: g_multi: fixed vendor and product ID commit 1c6529e92b7682573837e9c9eb7b5ba7a8216a88 upstream. This patch fixes the vendor and product ID the gadget uses by replacing the temporary IDs that were used during development (which should never get into mainline) with proper IDs. Signed-off-by: Michal Nazarewicz Signed-off-by: Kyungmin Park Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/multi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index a930d7fd7e7a..0ac051ec93b6 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -39,8 +39,8 @@ /*-------------------------------------------------------------------------*/ -#define MULTI_VENDOR_NUM 0x0525 /* XXX NetChip */ -#define MULTI_PRODUCT_NUM 0xa4ab /* XXX */ +#define MULTI_VENDOR_NUM 0x1d6b /* Linux Foundation */ +#define MULTI_PRODUCT_NUM 0x0104 /* Multifunction Composite Gadget */ /*-------------------------------------------------------------------------*/ -- cgit v1.2.3 From da768c0bacb071c078cdafd2fad9496c49f61659 Mon Sep 17 00:00:00 2001 From: Rich Mattes Date: Tue, 14 Sep 2010 00:35:40 -0400 Subject: USB: ftdi_sio: Add PID for accesio products commit 3126d8236ca6f68eb8292c6af22c2e59afbeef24 upstream. Adds support for Accesio USB to Serial adapters, which are built around FTDI FT232 UARTs. Tested with the Accesio USB-COM-4SM. Signed-off-by: Rich Mattes Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 0edf4b3741b4..953e075bf61a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -751,6 +751,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) }, + { USB_DEVICE(FTDI_VID, ACCESIO_COM4SM_PID) }, { USB_DEVICE(IONICS_VID, IONICS_PLUGCOMPUTER_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_24_MASTER_WING_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 15a4583775ad..02659f5c79e2 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1063,3 +1063,9 @@ * Submitted by John G. Rogers */ #define SEGWAY_RMP200_PID 0xe729 + + +/* + * Accesio USB Data Acquisition products (http://www.accesio.com/) + */ +#define ACCESIO_COM4SM_PID 0xD578 -- cgit v1.2.3 From 6f5fd62a25956b0f6f968fa8e28ceef9c275430e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sun, 12 Sep 2010 16:31:45 +0200 Subject: USB: ftdi_sio: revert "USB: ftdi_sio: fix DTR/RTS line modes" commit 677aeafe19e88c282af74564048243ccabb1c590 upstream. This reverts commit 6a1a82df91fa0eb1cc76069a9efe5714d087eccd. RTS and DTR should not be modified based on CRTSCTS when calling set_termios. Modem control lines are raised at port open by the tty layer and should stay raised regardless of whether hardware flow control is enabled or not. This is in conformance with the way serial ports work today and many applications depend on this behaviour to be able to talk to hardware implementing hardware flow control (without the applications actually using it). Hardware which expects different behaviour on these lines can always use TIOCMSET/TIOCMBI[SC] after port open to change them. Reported-by: Daniel Mack Reported-by: Dave Mielke Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 953e075bf61a..67984fdf715c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -2029,8 +2029,6 @@ static void ftdi_set_termios(struct tty_struct *tty, "urb failed to set to rts/cts flow control\n"); } - /* raise DTR/RTS */ - set_mctrl(port, TIOCM_DTR | TIOCM_RTS); } else { /* * Xon/Xoff code @@ -2078,8 +2076,6 @@ static void ftdi_set_termios(struct tty_struct *tty, } } - /* lower DTR/RTS */ - clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } return; } -- cgit v1.2.3 From b36f1df6971468a2e978765574b0ddf8bef8050e Mon Sep 17 00:00:00 2001 From: Rainer Keller Date: Tue, 28 Sep 2010 12:27:43 +0200 Subject: USB: add PID for FTDI based OpenDCC hardware commit 99c1e4f89d1033444ce4d0c064bd2826e81c3775 upstream. The OpenDCC project is developing a new hardware. This patch adds its PID to the list of known FTDI devices. The PID can be found at http://www.opendcc.de/elektronik/usb/opendcc_usb.html Signed-off-by: Rainer Keller Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 67984fdf715c..4d8b18eb5601 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -177,6 +177,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_SNIFFER_PID) }, { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) }, { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 02659f5c79e2..517d01435abb 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -61,6 +61,7 @@ #define FTDI_OPENDCC_SNIFFER_PID 0xBFD9 #define FTDI_OPENDCC_THROTTLE_PID 0xBFDA #define FTDI_OPENDCC_GATEWAY_PID 0xBFDB +#define FTDI_OPENDCC_GBM_PID 0xBFDC /* * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com) -- cgit v1.2.3 From af4701764369b0cd3fc652891ee12f6e736ad50a Mon Sep 17 00:00:00 2001 From: Daniel Suchy Date: Tue, 12 Oct 2010 15:44:24 +0200 Subject: USB: ftdi_sio: new VID/PIDs for various Papouch devices commit 59c6ccd9f9aecfa59c99ceba6d4d34b180547a05 upstream. This patch for FTDI USB serial driver ads new VID/PIDs used on various devices manufactured by Papouch (http://www.papouch.com). These devices have their own VID/PID, although they're using standard FTDI chip. In ftdi_sio.c, I also made small cleanup to have declarations for all Papouch devices together. Signed-off-by: Daniel Suchy Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 30 +++++++++++++++++++++++++++++- drivers/usb/serial/ftdi_sio_ids.h | 27 ++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 4d8b18eb5601..3eec27f38a8e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -675,7 +675,6 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, - { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) }, @@ -716,8 +715,37 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) }, + + /* Papouch devices based on FTDI chip */ + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_AP485_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB422_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485_2_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_AP485_2_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB422_2_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485S_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485C_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_LEC_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB232_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_IRAMP_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_DRAK5_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO8x8_PID) }, { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO2x2_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO10x1_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO30x3_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO60x3_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO2x16_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO3x32_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_DRAK6_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_UPSUSB_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_MU_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SIMUKEY_PID) }, { USB_DEVICE(PAPOUCH_VID, PAPOUCH_AD4USB_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_GMUX_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_GMSR_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DGQG_PID) }, { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) }, { USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 517d01435abb..fc44369ec1a6 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1023,9 +1023,34 @@ */ #define PAPOUCH_VID 0x5050 /* Vendor ID */ +#define PAPOUCH_SB485_PID 0x0100 /* Papouch SB485 USB-485/422 Converter */ +#define PAPOUCH_AP485_PID 0x0101 /* AP485 USB-RS485 Converter */ +#define PAPOUCH_SB422_PID 0x0102 /* Papouch SB422 USB-RS422 Converter */ +#define PAPOUCH_SB485_2_PID 0x0103 /* Papouch SB485 USB-485/422 Converter */ +#define PAPOUCH_AP485_2_PID 0x0104 /* AP485 USB-RS485 Converter */ +#define PAPOUCH_SB422_2_PID 0x0105 /* Papouch SB422 USB-RS422 Converter */ +#define PAPOUCH_SB485S_PID 0x0106 /* Papouch SB485S USB-485/422 Converter */ +#define PAPOUCH_SB485C_PID 0x0107 /* Papouch SB485C USB-485/422 Converter */ +#define PAPOUCH_LEC_PID 0x0300 /* LEC USB Converter */ +#define PAPOUCH_SB232_PID 0x0301 /* Papouch SB232 USB-RS232 Converter */ #define PAPOUCH_TMU_PID 0x0400 /* TMU USB Thermometer */ -#define PAPOUCH_QUIDO4x4_PID 0x0900 /* Quido 4/4 Module */ +#define PAPOUCH_IRAMP_PID 0x0500 /* Papouch IRAmp Duplex */ +#define PAPOUCH_DRAK5_PID 0x0700 /* Papouch DRAK5 */ +#define PAPOUCH_QUIDO8x8_PID 0x0800 /* Papouch Quido 8/8 Module */ +#define PAPOUCH_QUIDO4x4_PID 0x0900 /* Papouch Quido 4/4 Module */ +#define PAPOUCH_QUIDO2x2_PID 0x0a00 /* Papouch Quido 2/2 Module */ +#define PAPOUCH_QUIDO10x1_PID 0x0b00 /* Papouch Quido 10/1 Module */ +#define PAPOUCH_QUIDO30x3_PID 0x0c00 /* Papouch Quido 30/3 Module */ +#define PAPOUCH_QUIDO60x3_PID 0x0d00 /* Papouch Quido 60(100)/3 Module */ +#define PAPOUCH_QUIDO2x16_PID 0x0e00 /* Papouch Quido 2/16 Module */ +#define PAPOUCH_QUIDO3x32_PID 0x0f00 /* Papouch Quido 3/32 Module */ +#define PAPOUCH_DRAK6_PID 0x1000 /* Papouch DRAK6 */ +#define PAPOUCH_UPSUSB_PID 0x8000 /* Papouch UPS-USB adapter */ +#define PAPOUCH_MU_PID 0x8001 /* MU controller */ +#define PAPOUCH_SIMUKEY_PID 0x8002 /* Papouch SimuKey */ #define PAPOUCH_AD4USB_PID 0x8003 /* AD4USB Measurement Module */ +#define PAPOUCH_GMUX_PID 0x8004 /* Papouch GOLIATH MUX */ +#define PAPOUCH_GMSR_PID 0x8005 /* Papouch GOLIATH MSR */ /* * Marvell SheevaPlug -- cgit v1.2.3 From 3c95a4f95e6c492af203105c7d9315a9e0164b63 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 19 Oct 2010 09:05:43 -0700 Subject: USB: ftdi_sio: add device ids for ScienceScope commit 0f266abd70cd83571eca019f764b5f1992da7361 upstream. This adds the requested device ids to the ftdi_sio driver. Reported-by: Ewan Bingham Cc: Kuba Ober Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 3 +++ drivers/usb/serial/ftdi_sio_ids.h | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 3eec27f38a8e..e5438e67eaf1 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -791,6 +791,9 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MAXI_WING_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MEDIA_WING_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index fc44369ec1a6..cf1aea1b9ee7 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1095,3 +1095,8 @@ * Accesio USB Data Acquisition products (http://www.accesio.com/) */ #define ACCESIO_COM4SM_PID 0xD578 + +/* www.sciencescope.co.uk educational dataloggers */ +#define FTDI_SCIENCESCOPE_LOGBOOKML_PID 0xFF18 +#define FTDI_SCIENCESCOPE_LS_LOGBOOK_PID 0xFF1C +#define FTDI_SCIENCESCOPE_HS_LOGBOOK_PID 0xFF1D -- cgit v1.2.3 From 5b6ebed8ce478bf5392091c1359af3241ccea6e4 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 29 Sep 2010 09:54:29 +0300 Subject: USB: MUSB: fix kernel WARNING/oops when unloading module in OTG mode commit f405387435a85a440d1ce16f3ca36e042281643a upstream. Since commit 461972d8a4c94bc44f11a13046041c78a7cf18dd (musb_core: don't call musb_platform_exit() twice), unloading the driver module results in a WARNING "kobject: '(null)' (c73de788): is not initialized, yet kobject_put() is being called." (or even kernel oops) on e.g. DaVincis, though only in the OTG mode. There exists dubious and unbalanced put_device() call in musb_free() which takes place only in the OTG mode. As this commit caused musb_platform_exit() to be called (and so unregister the NOP transceiver) before this put_device() call, this function references already freed memory. On the other hand, all the glue layers miss the otg_put_transceiver() call, complementary to the otg_get_transceiver() call that they do. So, I think the solution is to get rid of the strange put_device() call, and instead call otg_put_transceiver() in the glue layers... Signed-off-by: Sergei Shtylyov Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/blackfin.c | 1 + drivers/usb/musb/davinci.c | 2 ++ drivers/usb/musb/musb_core.c | 4 ---- drivers/usb/musb/omap2430.c | 1 + drivers/usb/musb/tusb6010.c | 4 ++++ 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index b611420a8050..9733fe9b597a 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -397,5 +397,6 @@ int musb_platform_exit(struct musb *musb) gpio_free(musb->config->gpio_vrsel); + otg_put_transceiver(musb->xceiv); return 0; } diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 57624361c1de..6e67629f50cc 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -446,6 +446,7 @@ int __init musb_platform_init(struct musb *musb, void *board_data) fail: clk_disable(musb->clock); + otg_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return -ENODEV; } @@ -496,6 +497,7 @@ int musb_platform_exit(struct musb *musb) clk_disable(musb->clock); + otg_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return 0; diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 3b795c56221f..fbb768d2545b 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1922,10 +1922,6 @@ static void musb_free(struct musb *musb) dma_controller_destroy(c); } -#ifdef CONFIG_USB_MUSB_OTG - put_device(musb->xceiv->dev); -#endif - #ifdef CONFIG_USB_MUSB_HDRC_HCD usb_put_hcd(musb_to_hcd(musb)); #else diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index e06d65e36bf7..d57d9a412a8a 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -326,5 +326,6 @@ int musb_platform_exit(struct musb *musb) musb_platform_suspend(musb); + otg_put_transceiver(musb->xceiv); return 0; } diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 3c48e77a0aa2..bde40efc7046 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -1152,6 +1152,8 @@ done: if (ret < 0) { if (sync) iounmap(sync); + + otg_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); } return ret; @@ -1166,6 +1168,8 @@ int musb_platform_exit(struct musb *musb) musb->board_set_power(0); iounmap(musb->sync_va); + + otg_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return 0; } -- cgit v1.2.3 From 95112caf9788ae6d1e9385d79a202ffad4671921 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 29 Sep 2010 09:54:30 +0300 Subject: usb: musb: blackfin: call usb_nop_xceiv_unregister() in musb_platform_exit() commit 3daad24d6c72affdd40e8b6a75c87d3c175880b6 upstream. Blackfin's musb_platform_exit() forgets to call usb_nop_xceiv_unregister(). While fixing this, also remove the unneeded blank line there. Signed-off-by: Sergei Shtylyov Acked-by: Mike Frysinger Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/blackfin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index 9733fe9b597a..4fa25553c450 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -394,9 +394,9 @@ int __init musb_platform_init(struct musb *musb, void *board_data) int musb_platform_exit(struct musb *musb) { - gpio_free(musb->config->gpio_vrsel); otg_put_transceiver(musb->xceiv); + usb_nop_xceiv_unregister(); return 0; } -- cgit v1.2.3 From b6646b62d26b88762b2487d482ba3883bffa9398 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 29 Sep 2010 09:54:31 +0300 Subject: usb: musb: blackfin: call gpio_free() on error path in musb_platform_init() commit 00be545e49d83485d49a598d3b7e090088934be8 upstream. Blackfin's musb_platform_init() needs to call gpio_free() for error cleanup iff otg_get_transceiver() call returns NULL. Signed-off-by: Sergei Shtylyov Acked-by: Mike Frysinger Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/blackfin.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index 4fa25553c450..611a9d274363 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -342,8 +342,10 @@ int __init musb_platform_init(struct musb *musb, void *board_data) usb_nop_xceiv_register(); musb->xceiv = otg_get_transceiver(); - if (!musb->xceiv) + if (!musb->xceiv) { + gpio_free(musb->config->gpio_vrsel); return -ENODEV; + } if (ANOMALY_05000346) { bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value); -- cgit v1.2.3 From 86492f3cd2e888b0750f743ba62f5db07f5cd9ee Mon Sep 17 00:00:00 2001 From: Praveena Nadahally Date: Fri, 10 Sep 2010 23:05:03 +0530 Subject: USB: Change acm_iad_descriptor bFunctionProtocol to USB_CDC_ACM_PROTO_AT_V25TER commit 5c8db070b4480c43394680d9dfd2ddb06b97d2ae upstream. The protocol code is set 00 in IAD and it's set to 01 in ACM control interface descriptor in f_acm.c file. Due to this, windows is unable to install the modem(ACM) driver based on class-subclass-protocol matching. This patch corrects the protocol code in ACM IAD to the same as in acm_control_interface_desc protocol code. Acked-by: Linus Walleij Signed-off-by: Praveena Nadahally Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_acm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index d47a123f15ab..bd6226cbae86 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -111,7 +111,7 @@ acm_iad_descriptor = { .bInterfaceCount = 2, // control + data .bFunctionClass = USB_CLASS_COMM, .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, - .bFunctionProtocol = USB_CDC_PROTO_NONE, + .bFunctionProtocol = USB_CDC_ACM_PROTO_AT_V25TER, /* .iFunction = DYNAMIC */ }; -- cgit v1.2.3 From fde2940f72513468de5c85805e62f3226fbf54f4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 12 Sep 2010 11:41:50 -0300 Subject: USB: option: Add more ZTE modem USB id's commit ecfa153ef616b901e86d9a051b329fcda7a6ce7b upstream. There are lots of ZTE USB id's currently not covered by usb/serial. Adds them, to allow those devices to work properly on Linux. While here, put the USB ID's for 0x2002/0x2003 at the sorted order. This patch is based on zte.c file found on MF645. PS.: The ZTE driver is commenting the USB ID for 0x0053. It also adds, commented, an USB ID for 0x0026. Not sure why, but I think that 0053 is used by their devices in storage mode only. So, I opted to keep the comment on this patch. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 80c74d46c133..1987e6d1542e 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -595,6 +595,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0011, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0012, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0013, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0016, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff) }, @@ -606,38 +607,52 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0023, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0024, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0025, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) }, + /* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) }, */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0032, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0033, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0034, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0037, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0038, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0039, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0040, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0042, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0043, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0044, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0048, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0049, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0050, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0051, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0052, 0xff, 0xff, 0xff) }, + /* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0053, 0xff, 0xff, 0xff) }, */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0054, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0055, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0056, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0058, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0061, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0062, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0063, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0064, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0065, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0066, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0067, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0069, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0076, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0077, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0078, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0079, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0082, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0083, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0087, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0105, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0106, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0108, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff) }, @@ -853,6 +868,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) }, -- cgit v1.2.3 From 303dde705cccff507ab7fd35fccbcfff5806dcef Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Fri, 17 Sep 2010 11:09:06 -0400 Subject: USB: cp210x: Add Renesas RX-Stick device ID commit 2f1136d1d08a63dcdbcd462621373f30d8dfe590 upstream. RX610 development board by Renesas Bus 001 Device 024: ID 045b:0053 Hitachi, Ltd Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x045b Hitachi, Ltd idProduct 0x0053 bcdDevice 1.00 iManufacturer 1 Silicon Labs iProduct 2 RX-Stick iSerial 3 0001 . . . http://am.renesas.com/rx610stick Signed-off-by: DJ Delorie Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 8ed6ff6e861d..3ad53bd615b9 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -54,6 +54,7 @@ static int cp210x_carrier_raised(struct usb_serial_port *p); static int debug; static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */ { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ { USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */ -- cgit v1.2.3 From 5fc8fe8e2ea30805bee5a13420817d6ad34ea9ce Mon Sep 17 00:00:00 2001 From: Anders Larsen Date: Wed, 6 Oct 2010 23:46:25 +0200 Subject: USB: cp210x: Add WAGO 750-923 Service Cable device ID commit 93ad03d60b5b18897030038234aa2ebae8234748 upstream. The WAGO 750-923 USB Service Cable is used for configuration and firmware updates of several industrial automation products from WAGO Kontakttechnik GmbH. Bus 004 Device 002: ID 1be3:07a6 Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x1be3 idProduct 0x07a6 bcdDevice 1.00 iManufacturer 1 Silicon Labs iProduct 2 WAGO USB Service Cable iSerial 3 1277796751 . . . Signed-off-by: Anders Larsen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 3ad53bd615b9..9927bca29b3a 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -132,6 +132,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ + { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ { } /* Terminating Entry */ }; -- cgit v1.2.3 From d0aed2ec7c2374ddb4eccb7f5af2ffb7193ac014 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Mon, 20 Sep 2010 18:31:07 +0200 Subject: USB: atmel_usba_udc: force vbus_pin at -EINVAL when gpio_request failled commit 969affff54702785330de553b790372e261e93f9 upstream. to ensure gpio_is_valid return false Signed-off-by: Nicolas Ferre Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/atmel_usba_udc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index d623c7bda1f6..959f0624fe0d 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -2014,6 +2014,9 @@ static int __init usba_udc_probe(struct platform_device *pdev) } else { disable_irq(gpio_to_irq(udc->vbus_pin)); } + } else { + /* gpio_request fail so use -EINVAL for gpio_is_valid */ + ubc->vbus_pin = -EINVAL; } } -- cgit v1.2.3 From 554521a6fbb0d8d72db8c717a3e68eb508647f4e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 30 Sep 2010 15:16:23 -0400 Subject: USB: disable endpoints after unbinding interfaces, not before commit 80f0cf3947889014d3a3dc0ad60fb87cfda4b12a upstream. This patch (as1430) fixes a bug in usbcore. When a device configuration change occurs or a device is removed, the endpoints for the old config should be completely disabled. However it turns out they aren't; this is because usb_unbind_interface() calls usb_enable_interface() or usb_set_interface() to put interfaces back in altsetting 0, which re-enables the interfaces' endpoints. As a result, when a device goes through a config change or is unconfigured, the ep_in[] and ep_out[] arrays may be left holding old pointers to usb_host_endpoint structures. If the device is deauthorized these structures get freed, and the stale pointers cause errors when the the device is eventually unplugged. The solution is to disable the endpoints after unbinding the interfaces instead of before. This isn't as large a change as it sounds, since usb_unbind_interface() disables all the interface's endpoints anyway before calling the driver's disconnect routine, unless the driver claims to support "soft" unbind. This fixes Bugzilla #19192. Thanks to "Tom" Lei Ming for diagnosing the underlying cause of the problem. Signed-off-by: Alan Stern Tested-by: Carsten Sommer Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 9f0ce7de0e36..d6e3e410477e 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1140,13 +1140,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) { int i; - dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__, - skip_ep0 ? "non-ep0" : "all"); - for (i = skip_ep0; i < 16; ++i) { - usb_disable_endpoint(dev, i, true); - usb_disable_endpoint(dev, i + USB_DIR_IN, true); - } - /* getting rid of interfaces will disconnect * any drivers bound to them (a key side effect) */ @@ -1176,6 +1169,13 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) if (dev->state == USB_STATE_CONFIGURED) usb_set_device_state(dev, USB_STATE_ADDRESS); } + + dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__, + skip_ep0 ? "non-ep0" : "all"); + for (i = skip_ep0; i < 16; ++i) { + usb_disable_endpoint(dev, i, true); + usb_disable_endpoint(dev, i + USB_DIR_IN, true); + } } /** -- cgit v1.2.3 From 867b3d875ffd9f3c6ee23506dce7e20833948d55 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 12 Oct 2010 01:07:05 +0200 Subject: USB: visor: fix initialisation of UX50/TH55 devices commit cfb8da8f69b81d367b766888e83ec0483a31bf01 upstream. Fix regression introduced by commit 214916f2ec6701e1c9972f26c60b3dc37d3153c6 (USB: visor: reimplement using generic framework) which broke initialisation of UX50/TH55 devices that used re-mapped bulk-out endpoint addresses. Reported-by: Robert Gadsdon Tested-by: Robert Gadsdon Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/visor.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index eb76aaef4268..15a5d89b7f39 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -606,6 +606,10 @@ static int treo_attach(struct usb_serial *serial) static int clie_5_attach(struct usb_serial *serial) { + struct usb_serial_port *port; + unsigned int pipe; + int j; + dbg("%s", __func__); /* TH55 registers 2 ports. @@ -621,9 +625,14 @@ static int clie_5_attach(struct usb_serial *serial) return -1; /* port 0 now uses the modified endpoint Address */ - serial->port[0]->bulk_out_endpointAddress = + port = serial->port[0]; + port->bulk_out_endpointAddress = serial->port[1]->bulk_out_endpointAddress; + pipe = usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress); + for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) + port->write_urbs[j]->pipe = pipe; + return 0; } -- cgit v1.2.3 From 973d98819ea61350ce7905c4211441bed74b5c5c Mon Sep 17 00:00:00 2001 From: Alon Ziv Date: Sun, 10 Oct 2010 08:32:18 +0200 Subject: USB: opticon: Fix long-standing bugs in opticon driver commit 97cd8dc4ca9a1a5efb2cc38758e01492e3b013e2 upstream. The bulk-read callback had two bugs: a) The bulk-in packet's leading two zeros were returned (and the two last bytes truncated) b) The wrong URB was transmitted for the second (and later) read requests, causing further reads to return the entire packet (including leading zeros) Signed-off-by: Alon Ziv Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index ed01f3b2de8c..9ff19c8a122e 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -96,8 +96,8 @@ static void opticon_bulk_callback(struct urb *urb) /* real data, send it to the tty layer */ tty = tty_port_tty_get(&port->port); if (tty) { - tty_insert_flip_string(tty, data, - data_length); + tty_insert_flip_string(tty, data + 2, + data_length); tty_flip_buffer_push(tty); tty_kref_put(tty); } @@ -130,7 +130,7 @@ exit: priv->bulk_address), priv->bulk_in_buffer, priv->buffer_size, opticon_bulk_callback, priv); - result = usb_submit_urb(port->read_urb, GFP_ATOMIC); + result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC); if (result) dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", -- cgit v1.2.3 From 3952e7d5fa77c441a0e29c19009f4988da916b9c Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 14 Oct 2010 14:52:54 +0900 Subject: usb: r8a66597-hcd: Change mistake of the outsw function commit ac9dfe9cdda4eb42ecaa9f13b0fee518e0b6518e upstream. Some functions changed by 1c98347e613bf17ea2f18c9766ce0ab77f65a96d. However, There was a change mistake of the function (outsw). Signed-off-by: Nobuhiro Iwamatsu CC: Paul Mundt Acked-by: Yoshihiro Shimoda Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/r8a66597.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h index 95d0f5adfdcf..25563e9a90bc 100644 --- a/drivers/usb/host/r8a66597.h +++ b/drivers/usb/host/r8a66597.h @@ -227,7 +227,7 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, int odd = len & 0x0001; len = len / 2; - ioread16_rep(fifoaddr, buf, len); + iowrite16_rep(fifoaddr, buf, len); if (unlikely(odd)) { buf = &buf[len]; iowrite8((unsigned char)*buf, fifoaddr); -- cgit v1.2.3 From 21a0f6c9649fabd0b964419982a609d9543e054e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 14 Oct 2010 15:25:21 -0400 Subject: USB: accept some invalid ep0-maxpacket values commit 56626a72a47bf3e50875d960d6b5f17b9bee0ab2 upstream. A few devices (such as the RCA VR5220 voice recorder) are so non-compliant with the USB spec that they have invalid maxpacket sizes for endpoint 0. Nevertheless, as long as we can safely use them, we may as well do so. This patch (as1432) softens our acceptance criterion by allowing high-speed devices to have ep0-maxpacket sizes other than 64. A warning is printed in the system log when this happens, and the existing error message is clarified. Signed-off-by: Alan Stern Reported-by: James Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index ffc80e3241e1..53467b526b12 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2859,13 +2859,16 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, else i = udev->descriptor.bMaxPacketSize0; if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) { - if (udev->speed != USB_SPEED_FULL || + if (udev->speed == USB_SPEED_LOW || !(i == 8 || i == 16 || i == 32 || i == 64)) { - dev_err(&udev->dev, "ep0 maxpacket = %d\n", i); + dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i); retval = -EMSGSIZE; goto fail; } - dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i); + if (udev->speed == USB_SPEED_FULL) + dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i); + else + dev_warn(&udev->dev, "Using ep0 maxpacket: %d\n", i); udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i); usb_ep0_reinit(udev); } -- cgit v1.2.3 From 616ab3c99a971ec876f7db7f396ea0766347be9f Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Tue, 24 Aug 2010 09:30:46 +0200 Subject: asus-laptop: fix gps rfkill commit 23f45c3a76e715217f40ac397c15815c774cad7f upstream. The GPS rfkill crappy code. The ops_data argument wasn't set, and was totally misused. The fix have been tested on an Asus R2H. Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/asus-laptop.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index efe8f6388906..1fccc8503757 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -1064,9 +1064,9 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr, */ static int asus_gps_rfkill_set(void *data, bool blocked) { - acpi_handle handle = data; + struct asus_laptop *asus = data; - return asus_gps_switch(handle, !blocked); + return asus_gps_switch(asus, !blocked); } static const struct rfkill_ops asus_gps_rfkill_ops = { @@ -1093,7 +1093,7 @@ static int asus_rfkill_init(struct asus_laptop *asus) asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev, RFKILL_TYPE_GPS, - &asus_gps_rfkill_ops, NULL); + &asus_gps_rfkill_ops, asus); if (!asus->gps_rfkill) return -EINVAL; -- cgit v1.2.3 From c5b2751c1bd98bcab5f79bba0c771ef641c14283 Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Mon, 20 Sep 2010 11:20:22 -0500 Subject: sd name space exhaustion causes system hang commit 1a03ae0f556a931aa3747b70e44b78308f5b0590 upstream. Following a site power outage which re-enabled all the ports on my FC switches, my system subsequently booted with far too many luns! I had let it run hoping it would make multi-user. It didn't. :( It hung solid after exhausting the last sd device, sdzzz, and attempting to create sdaaaa and beyond. I was unable to get a dump. Discovered using a 2.6.32.13 based system. correct this by detecting when the last index is utilized and failing the sd probe of the device. Patch applies to scsi-misc-2.6. Signed-off-by: Michael Reed Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/sd.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8802e48bc063..e4d9c515c292 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2204,11 +2204,10 @@ static void sd_probe_async(void *data, async_cookie_t cookie) index = sdkp->index; dev = &sdp->sdev_gendev; - if (index < SD_MAX_DISKS) { - gd->major = sd_major((index & 0xf0) >> 4); - gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); - gd->minors = SD_MINORS; - } + gd->major = sd_major((index & 0xf0) >> 4); + gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); + gd->minors = SD_MINORS; + gd->fops = &sd_fops; gd->private_data = &sdkp->driver; gd->queue = sdkp->device->request_queue; @@ -2297,6 +2296,12 @@ static int sd_probe(struct device *dev) if (error) goto out_put; + if (index >= SD_MAX_DISKS) { + error = -ENODEV; + sdev_printk(KERN_WARNING, sdp, "SCSI disk (sd) name space exhausted.\n"); + goto out_free_index; + } + error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN); if (error) goto out_free_index; -- cgit v1.2.3 From 77bfbe19958b2640a8bef2abc142d1b0d4dc9d83 Mon Sep 17 00:00:00 2001 From: David Milburn Date: Fri, 3 Sep 2010 17:13:03 -0500 Subject: libsas: fix NCQ mixing with non-NCQ commit f0ad30d3d2dc924decc0e10b1ff6dc32525a5d99 upstream. Some cards (like mvsas) have issue troubles if non-NCQ commands are mixed with NCQ ones. Fix this by using the libata default NCQ check routine which waits until all NCQ commands are complete before issuing a non-NCQ one. The impact to cards (like aic94xx) which don't need this logic should be minimal Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/libsas/sas_ata.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 8c496b56556c..fb788566adae 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -347,6 +347,7 @@ static int sas_ata_scr_read(struct ata_link *link, unsigned int sc_reg_in, static struct ata_port_operations sas_sata_ops = { .phy_reset = sas_ata_phy_reset, .post_internal_cmd = sas_ata_post_internal, + .qc_defer = ata_std_qc_defer, .qc_prep = ata_noop_qc_prep, .qc_issue = sas_ata_qc_issue, .qc_fill_rtf = sas_ata_qc_fill_rtf, -- cgit v1.2.3 From 5934df9ba53c1d09c76c672cd430592c74404981 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Oct 2010 09:03:07 +0200 Subject: gdth: integer overflow in ioctl commit f63ae56e4e97fb12053590e41a4fa59e7daa74a4 upstream. gdth_ioctl_alloc() takes the size variable as an int. copy_from_user() takes the size variable as an unsigned long. gen.data_len and gen.sense_len are unsigned longs. On x86_64 longs are 64 bit and ints are 32 bit. We could pass in a very large number and the allocation would truncate the size to 32 bits and allocate a small buffer. Then when we do the copy_from_user(), it would result in a memory corruption. Signed-off-by: Dan Carpenter Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/gdth.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index f672d6213eea..3ccbf76012fa 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -4175,6 +4175,14 @@ static int ioc_general(void __user *arg, char *cmnd) ha = gdth_find_ha(gen.ionode); if (!ha) return -EFAULT; + + if (gen.data_len > INT_MAX) + return -EINVAL; + if (gen.sense_len > INT_MAX) + return -EINVAL; + if (gen.data_len + gen.sense_len > INT_MAX) + return -EINVAL; + if (gen.data_len + gen.sense_len != 0) { if (!(buf = gdth_ioctl_alloc(ha, gen.data_len + gen.sense_len, FALSE, &paddr))) -- cgit v1.2.3 From 6ed019fa8d1fac16cb3d42545bce4a811b17f32a Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 6 Oct 2010 13:19:44 +0200 Subject: Fix race when removing SCSI devices commit 546ae796bfac6399e30da4b5af2cf7a6d0f8a4ec upstream. Removing SCSI devices through echo 1 > /sys/bus/scsi/devices/ ... /delete while the FC transport class removes the SCSI target can lead to an oops: Unable to handle kernel pointer dereference at virtual kernel address 00000000b6815000 Oops: 0011 [#1] PREEMPT SMP DEBUG_PAGEALLOC Modules linked in: sunrpc qeth_l3 binfmt_misc dm_multipath scsi_dh dm_mod ipv6 qeth ccwgroup [last unloaded: scsi_wait_scan] CPU: 1 Not tainted 2.6.35.5-45.x.20100924-s390xdefault #1 Process fc_wq_0 (pid: 861, task: 00000000b7331240, ksp: 00000000b735bac0) Krnl PSW : 0704200180000000 00000000003ff6e4 (__scsi_remove_device+0x24/0xd0) R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:0 CC:2 PM:0 EA:3 Krnl GPRS: 0000000000000001 0000000000000000 00000000b6815000 00000000bc24a8c0 00000000003ff7c8 000000000056dbb8 0000000000000002 0000000000835d80 ffffffff00000000 0000000000001000 00000000b6815000 00000000bc24a7f0 00000000b68151a0 00000000b6815000 00000000b735bc20 00000000b735bbf8 Krnl Code: 00000000003ff6d6: a7840001 brc 8,3ff6d8 00000000003ff6da: a7fbffd8 aghi %r15,-40 00000000003ff6de: e3e0f0980024 stg %r14,152(%r15) >00000000003ff6e4: e31021200004 lg %r1,288(%r2) 00000000003ff6ea: a71f0000 cghi %r1,0 00000000003ff6ee: a7a40011 brc 10,3ff710 00000000003ff6f2: a7390003 lghi %r3,3 00000000003ff6f6: c0e5ffffc8b1 brasl %r14,3f8858 Call Trace: ([<0000000000001000>] 0x1000) [<00000000003ff7d2>] scsi_remove_device+0x42/0x54 [<00000000003ff8ba>] __scsi_remove_target+0xca/0xfc [<00000000003ff99a>] __remove_child+0x3a/0x48 [<00000000003e3246>] device_for_each_child+0x72/0xbc [<00000000003ff93a>] scsi_remove_target+0x4e/0x74 [<0000000000406586>] fc_rport_final_delete+0xb2/0x23c [<000000000015d080>] worker_thread+0x200/0x344 [<000000000016330c>] kthread+0xa0/0xa8 [<0000000000106c1a>] kernel_thread_starter+0x6/0xc [<0000000000106c14>] kernel_thread_starter+0x0/0xc INFO: lockdep is turned off. Last Breaking-Event-Address: [<00000000003ff7cc>] scsi_remove_device+0x3c/0x54 The function __scsi_remove_target iterates through the SCSI devices on the host, but it drops the host_lock before calling scsi_remove_device. When the SCSI device is deleted from another thread, the pointer to the SCSI device in scsi_remove_device can become invalid. Fix this by getting a reference to the SCSI device before dropping the host_lock to keep the SCSI device alive for the call to scsi_remove_device. Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_sysfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index c23ab978c3ba..86ea5f3e74ea 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -990,10 +990,11 @@ static void __scsi_remove_target(struct scsi_target *starget) list_for_each_entry(sdev, &shost->__devices, siblings) { if (sdev->channel != starget->channel || sdev->id != starget->id || - sdev->sdev_state == SDEV_DEL) + scsi_device_get(sdev)) continue; spin_unlock_irqrestore(shost->host_lock, flags); scsi_remove_device(sdev); + scsi_device_put(sdev); spin_lock_irqsave(shost->host_lock, flags); goto restart; } -- cgit v1.2.3 From 01660e27512db9b64070d66f95431b5869bd1b8c Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 6 Oct 2010 03:10:59 -0500 Subject: Fix regressions in scsi_internal_device_block commit 986fe6c7f50974e871b8ab5a800f5310ea25b361 upstream. Deleting a SCSI device on a blocked fc_remote_port (before fast_io_fail_tmo fires) results in a hanging thread: STACK: 0 schedule+1108 [0x5cac48] 1 schedule_timeout+528 [0x5cb7fc] 2 wait_for_common+266 [0x5ca6be] 3 blk_execute_rq+160 [0x354054] 4 scsi_execute+324 [0x3b7ef4] 5 scsi_execute_req+162 [0x3b80ca] 6 sd_sync_cache+138 [0x3cf662] 7 sd_shutdown+138 [0x3cf91a] 8 sd_remove+112 [0x3cfe4c] 9 __device_release_driver+124 [0x3a08b8] 10 device_release_driver+60 [0x3a0a5c] 11 bus_remove_device+266 [0x39fa76] 12 device_del+340 [0x39d818] 13 __scsi_remove_device+204 [0x3bcc48] 14 scsi_remove_device+66 [0x3bcc8e] 15 sysfs_schedule_callback_work+50 [0x260d66] 16 worker_thread+622 [0x162326] 17 kthread+160 [0x1680b0] 18 kernel_thread_starter+6 [0x10aaea] During the delete, the SCSI device is in moved to SDEV_CANCEL. When the FC transport class later calls scsi_target_unblock, this has no effect, since scsi_internal_device_unblock ignores SCSI devics in this state. It looks like all these are regressions caused by: 5c10e63c943b4c67561ddc6bf61e01d4141f881f [SCSI] limit state transitions in scsi_internal_device_unblock Fix by rejecting offline and cancel in the state transition. Signed-off-by: Christof Schmitt [jejb: Original patch by Christof Schmitt, modified by Mike Christie] Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 1646fe7cbd4b..9cc450b8f942 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2436,7 +2436,8 @@ scsi_internal_device_unblock(struct scsi_device *sdev) sdev->sdev_state = SDEV_RUNNING; else if (sdev->sdev_state == SDEV_CREATED_BLOCK) sdev->sdev_state = SDEV_CREATED; - else + else if (sdev->sdev_state != SDEV_CANCEL && + sdev->sdev_state != SDEV_OFFLINE) return -EINVAL; spin_lock_irqsave(q->queue_lock, flags); -- cgit v1.2.3 From d6a9416394b2556d67f0aebfeb6821812e5960b4 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 11 Oct 2010 12:23:25 -0700 Subject: net: clear heap allocations for privileged ethtool actions [ Upstream commit b00916b189d13a615ff05c9242201135992fcda3 ] Several other ethtool functions leave heap uncleared (potentially) by drivers. Some interfaces appear safe (eeprom, etc), in that the sizes are well controlled. In some situations (e.g. unchecked error conditions), the heap will remain unchanged in areas before copying back to userspace. Note that these are less of an issue since these all require CAP_NET_ADMIN. Cc: stable@kernel.org Signed-off-by: Kees Cook Acked-by: Ben Hutchings Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/ethtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 75e4ffeb8cc9..f5e38561688f 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -482,7 +482,7 @@ static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr) gstrings.len = ret; - data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); + data = kzalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); if (!data) return -ENOMEM; @@ -719,7 +719,7 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) if (regs.len > reglen) regs.len = reglen; - regbuf = kmalloc(reglen, GFP_USER); + regbuf = kzalloc(reglen, GFP_USER); if (!regbuf) return -ENOMEM; -- cgit v1.2.3 From d27645006b5e2b136c0dd8d87e0c4d73612129d5 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 13 Oct 2010 09:19:55 +0000 Subject: gianfar: fix double lock typo [ Upstream commit 9756403b16cfeda85efe77e62832a2f6b5752fdf ] This should be a _restore() instead of a _save(). Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/gianfar_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 9bda023c0235..ddab7036e375 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c @@ -538,7 +538,7 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data) unlock_tx_qs(priv); unlock_rx_qs(priv); - local_irq_save(flags); + local_irq_restore(flags); for (i = 0; i < priv->num_rx_queues; i++) gfar_clean_rx_ring(priv->rx_queue[i], -- cgit v1.2.3 From 4d7fa13e13b6d9cf4d2ed085d8c093dc6c6b549e Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Tue, 19 Oct 2010 00:06:36 +0000 Subject: gianfar: Fix crashes on RX path (Was Re: [Bugme-new] [Bug 19692] New: linux-2.6.36-rc5 crash with gianfar ethernet at full line rate traffic) [ Upstream commit 0d1fe1111c667e9c713d7efc7ae468a605f236a4 ] The rx_recycle queue is global per device but can be accesed by many napi handlers at the same time, so it needs full skb_queue primitives (with locking). Otherwise, various crashes caused by broken skbs are possible. This patch resolves, at least partly, bugzilla bug 19692. (Because of some doubts that there could be still something around which is hard to reproduce my proposal is to leave this bug opened for a month.) Fixes commit: 0fd56bb5be6455d0d42241e65aed057244665e5e ("gianfar: Add support for skb recycling") Reported-by: emin ak Tested-by: emin ak Signed-off-by: Jarek Poplawski CC: Andy Fleming Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/gianfar.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 28b53d1cd4f1..26a1aca8e19c 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -2427,7 +2427,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) if (skb_queue_len(&priv->rx_recycle) < rx_queue->rx_ring_size && skb_recycle_check(skb, priv->rx_buffer_size + RXBUF_ALIGNMENT)) - __skb_queue_head(&priv->rx_recycle, skb); + skb_queue_head(&priv->rx_recycle, skb); else dev_kfree_skb_any(skb); @@ -2498,7 +2498,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev) struct gfar_private *priv = netdev_priv(dev); struct sk_buff *skb = NULL; - skb = __skb_dequeue(&priv->rx_recycle); + skb = skb_dequeue(&priv->rx_recycle); if (!skb) skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT); @@ -2675,7 +2675,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) * recycle list. */ skb_reserve(skb, -GFAR_CB(skb)->alignamount); - __skb_queue_head(&priv->rx_recycle, skb); + skb_queue_head(&priv->rx_recycle, skb); } } else { /* Increment the number of packets */ -- cgit v1.2.3 From f75c81af1527ad2a4d413ee03c55afdc681e4392 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 21 Sep 2010 08:47:45 +0000 Subject: ip: fix truesize mismatch in ip fragmentation [ Upstream commit 3d13008e7345fa7a79d8f6438150dc15d6ba6e9d ] Special care should be taken when slow path is hit in ip_fragment() : When walking through frags, we transfert truesize ownership from skb to frags. Then if we hit a slow_path condition, we must undo this or risk uncharging frags->truesize twice, and in the end, having negative socket sk_wmem_alloc counter, or even freeing socket sooner than expected. Many thanks to Nick Bowler, who provided a very clean bug report and test program. Thanks to Jarek for reviewing my first patch and providing a V2 While Nick bisection pointed to commit 2b85a34e911 (net: No more expensive sock_hold()/sock_put() on each tx), underlying bug is older (2.6.12-rc5) A side effect is to extend work done in commit b2722b1c3a893e (ip_fragment: also adjust skb->truesize for packets not owned by a socket) to ipv6 as well. Reported-and-bisected-by: Nick Bowler Tested-by: Nick Bowler Signed-off-by: Eric Dumazet CC: Jarek Poplawski CC: Patrick McHardy Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ip_output.c | 19 +++++++++++++------ net/ipv6/ip6_output.c | 18 +++++++++++++----- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 041d41df1224..f300f43eeb1f 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -488,9 +488,8 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) * we can switch to copy when see the first bad fragment. */ if (skb_has_frags(skb)) { - struct sk_buff *frag; + struct sk_buff *frag, *frag2; int first_len = skb_pagelen(skb); - int truesizes = 0; if (first_len - hlen > mtu || ((first_len - hlen) & 7) || @@ -503,18 +502,18 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) if (frag->len > mtu || ((frag->len & 7) && frag->next) || skb_headroom(frag) < hlen) - goto slow_path; + goto slow_path_clean; /* Partially cloned skb? */ if (skb_shared(frag)) - goto slow_path; + goto slow_path_clean; BUG_ON(frag->sk); if (skb->sk) { frag->sk = skb->sk; frag->destructor = sock_wfree; } - truesizes += frag->truesize; + skb->truesize -= frag->truesize; } /* Everything is OK. Generate! */ @@ -524,7 +523,6 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) frag = skb_shinfo(skb)->frag_list; skb_frag_list_init(skb); skb->data_len = first_len - skb_headlen(skb); - skb->truesize -= truesizes; skb->len = first_len; iph->tot_len = htons(first_len); iph->frag_off = htons(IP_MF); @@ -576,6 +574,15 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) } IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS); return err; + +slow_path_clean: + skb_walk_frags(skb, frag2) { + if (frag2 == frag) + break; + frag2->sk = NULL; + frag2->destructor = NULL; + skb->truesize += frag2->truesize; + } } slow_path: diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 89425af0684c..00a0bbe79aec 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -639,7 +639,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) if (skb_has_frags(skb)) { int first_len = skb_pagelen(skb); - int truesizes = 0; + struct sk_buff *frag2; if (first_len - hlen > mtu || ((first_len - hlen) & 7) || @@ -651,18 +651,18 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) if (frag->len > mtu || ((frag->len & 7) && frag->next) || skb_headroom(frag) < hlen) - goto slow_path; + goto slow_path_clean; /* Partially cloned skb? */ if (skb_shared(frag)) - goto slow_path; + goto slow_path_clean; BUG_ON(frag->sk); if (skb->sk) { frag->sk = skb->sk; frag->destructor = sock_wfree; - truesizes += frag->truesize; } + skb->truesize -= frag->truesize; } err = 0; @@ -693,7 +693,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) first_len = skb_pagelen(skb); skb->data_len = first_len - skb_headlen(skb); - skb->truesize -= truesizes; skb->len = first_len; ipv6_hdr(skb)->payload_len = htons(first_len - sizeof(struct ipv6hdr)); @@ -756,6 +755,15 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) IPSTATS_MIB_FRAGFAILS); dst_release(&rt->u.dst); return err; + +slow_path_clean: + skb_walk_frags(skb, frag2) { + if (frag2 == frag) + break; + frag2->sk = NULL; + frag2->destructor = NULL; + skb->truesize += frag2->truesize; + } } slow_path: -- cgit v1.2.3 From 03b965ed6e985cd528b5a2eda0b2ddcb9fd542ef Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Sun, 24 Oct 2010 23:06:43 +0000 Subject: ipv6: fix refcnt problem related to POSTDAD state [ Upstream commit 801715f95be37b865af83b9909ad93da141a9306 ] After running this bonding setup script modprobe bonding miimon=100 mode=0 max_bonds=1 ifconfig bond0 10.1.1.1/16 ifenslave bond0 eth1 ifenslave bond0 eth3 on s390 with qeth-driven slaves, modprobe -r fails with this message unregister_netdevice: waiting for bond0 to become free. Usage count = 1 due to twice detection of duplicate address. Problem is caused by a missing decrease of ifp->refcnt in addrconf_dad_failure. An extra call of in6_ifa_put(ifp) solves it. Problem has been introduced with commit f2344a131bccdbfc5338e17fa71a807dee7944fa. Signed-off-by: Ursula Braun Cc: David S. Miller Cc: Herbert Xu Acked-by: Herbert Xu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/addrconf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 784f34d11fdd..0bbaddc32935 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1424,8 +1424,10 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) { struct inet6_dev *idev = ifp->idev; - if (addrconf_dad_end(ifp)) + if (addrconf_dad_end(ifp)) { + in6_ifa_put(ifp); return; + } if (net_ratelimit()) printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n", -- cgit v1.2.3 From 971962be8667ef802e0ad8e55ec192747bbf31e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Sun, 3 Oct 2010 14:49:00 -0700 Subject: net: Fix IPv6 PMTU disc. w/ asymmetric routes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit ae878ae280bea286ff2b1e1cb6e609dd8cb4501d ] Signed-off-by: Maciej Żenczykowski Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/route.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 252d76199c41..4d947c131937 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1559,14 +1559,13 @@ out: * i.e. Path MTU discovery */ -void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, - struct net_device *dev, u32 pmtu) +static void rt6_do_pmtu_disc(struct in6_addr *daddr, struct in6_addr *saddr, + struct net *net, u32 pmtu, int ifindex) { struct rt6_info *rt, *nrt; - struct net *net = dev_net(dev); int allfrag = 0; - rt = rt6_lookup(net, daddr, saddr, dev->ifindex, 0); + rt = rt6_lookup(net, daddr, saddr, ifindex, 0); if (rt == NULL) return; @@ -1634,6 +1633,27 @@ out: dst_release(&rt->u.dst); } +void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, + struct net_device *dev, u32 pmtu) +{ + struct net *net = dev_net(dev); + + /* + * RFC 1981 states that a node "MUST reduce the size of the packets it + * is sending along the path" that caused the Packet Too Big message. + * Since it's not possible in the general case to determine which + * interface was used to send the original packet, we update the MTU + * on the interface that will be used to send future packets. We also + * update the MTU on the interface that received the Packet Too Big in + * case the original packet was forced out that interface with + * SO_BINDTODEVICE or similar. This is the next best thing to the + * correct behaviour, which would be to update the MTU on all + * interfaces. + */ + rt6_do_pmtu_disc(daddr, saddr, net, pmtu, 0); + rt6_do_pmtu_disc(daddr, saddr, net, pmtu, dev->ifindex); +} + /* * Misc support functions */ -- cgit v1.2.3 From cf557ed8e65848790ec4acbb9311ab8abb2df3da Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 21 Sep 2010 13:04:04 -0700 Subject: netxen: dont set skb->truesize [ Upstream commit 7e96dc7045bff8758804b047c0dfb6868f182500 ] skb->truesize is set in core network. Dont change it unless dealing with fragments. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/netxen/netxen_nic_init.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index c865dda2adf1..81f982aa334c 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -1540,7 +1540,6 @@ netxen_process_rcv(struct netxen_adapter *adapter, if (pkt_offset) skb_pull(skb, pkt_offset); - skb->truesize = skb->len + sizeof(struct sk_buff); skb->protocol = eth_type_trans(skb, netdev); napi_gro_receive(&sds_ring->napi, skb); @@ -1602,8 +1601,6 @@ netxen_process_lro(struct netxen_adapter *adapter, skb_put(skb, lro_length + data_offset); - skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb); - skb_pull(skb, l2_hdr_offset); skb->protocol = eth_type_trans(skb, netdev); -- cgit v1.2.3 From f38eaf1feb023c286b3c5e37185feb39b8b78b36 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 20 Sep 2010 02:28:59 +0000 Subject: qlcnic: dont set skb->truesize [ Upstream commit 8df8fd27123054b02007361bd5483775db84b4a8 ] skb->truesize is set in core network. Dont change it unless dealing with fragments. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/qlcnic/qlcnic_init.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 71a4e664ad76..a4c69d59ef0f 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -1363,7 +1363,6 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter, if (pkt_offset) skb_pull(skb, pkt_offset); - skb->truesize = skb->len + sizeof(struct sk_buff); skb->protocol = eth_type_trans(skb, netdev); napi_gro_receive(&sds_ring->napi, skb); @@ -1425,8 +1424,6 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, skb_put(skb, lro_length + data_offset); - skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb); - skb_pull(skb, l2_hdr_offset); skb->protocol = eth_type_trans(skb, netdev); @@ -1659,8 +1656,6 @@ qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, if (pkt_offset) skb_pull(skb, pkt_offset); - skb->truesize = skb->len + sizeof(struct sk_buff); - if (!qlcnic_check_loopback_buff(skb->data)) adapter->diag_cnt++; -- cgit v1.2.3 From 2556c3ee6403113deb5a310826e80132adb3b1ee Mon Sep 17 00:00:00 2001 From: Kumar Sanghvi Date: Mon, 27 Sep 2010 23:10:42 +0000 Subject: Phonet: Correct header retrieval after pskb_may_pull MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit a91e7d471e2e384035b9746ea707ccdcd353f5dd ] Retrieve the header after doing pskb_may_pull since, pskb_may_pull could change the buffer structure. This is based on the comment given by Eric Dumazet on Phonet Pipe controller patch for a similar problem. Signed-off-by: Kumar Sanghvi Acked-by: Linus Walleij Acked-by: Eric Dumazet Acked-by: Rémi Denis-Courmont Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/phonet/pep.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/phonet/pep.c b/net/phonet/pep.c index b2a3ae6cad78..15003021f4f0 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -225,12 +225,13 @@ static void pipe_grant_credits(struct sock *sk) static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb) { struct pep_sock *pn = pep_sk(sk); - struct pnpipehdr *hdr = pnp_hdr(skb); + struct pnpipehdr *hdr; int wake = 0; if (!pskb_may_pull(skb, sizeof(*hdr) + 4)) return -EINVAL; + hdr = pnp_hdr(skb); if (hdr->data[0] != PN_PEP_TYPE_COMMON) { LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP type: %u\n", (unsigned)hdr->data[0]); -- cgit v1.2.3 From ebe60f3215a4d398aa348987f027597d582b50ec Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 14 Oct 2010 17:41:53 +0000 Subject: r6040: Fix multicast filter some more [ Upstream commit e2269308359d5863b6aa1fcb95a425a2ab255f1f ] This code has been broken forever, but in several different and creative ways. So far as I can work out, the R6040 MAC filter has 4 exact-match entries, the first of which the driver uses for its assigned unicast address, plus a 64-entry hash-based filter for multicast addresses (maybe unicast as well?). The original version of this code would write the first 4 multicast addresses as exact-match entries from offset 1 (bug #1: there is no entry 4 so this could write to some PHY registers). It would fill the remainder of the exact-match entries with the broadcast address (bug #2: this would overwrite the last used entry). If more than 4 multicast addresses were configured, it would set up the hash table, write some random crap to the MAC control register (bug #3) and finally walk off the end of the list when filling the exact-match entries (bug #4). All of this seems to be pointless, since it sets the promiscuous bit when the interface is made promiscuous or if >4 multicast addresses are enabled, and never clears it (bug #5, masking bug #2). The recent(ish) changes to the multicast list fixed bug #4, but completely removed the limit on iteration over the exact-match entries (bug #6). Bug #4 was reported as and more recently as . Florian Fainelli attempted to fix these in commit 3bcf8229a8c49769e48d3e0bd1e20d8e003f8106, but that actually dealt with bugs #1-3, bug #4 having been fixed in mainline at that point. That commit fixes the most important current bug #6. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/r6040.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 9a251acf5ab8..b7758d38a1cf 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -988,16 +988,18 @@ static void r6040_multicast_list(struct net_device *dev) /* Multicast Address 1~4 case */ i = 0; netdev_for_each_mc_addr(ha, dev) { - if (i < MCAST_MAX) { - adrp = (u16 *) ha->addr; - iowrite16(adrp[0], ioaddr + MID_1L + 8 * i); - iowrite16(adrp[1], ioaddr + MID_1M + 8 * i); - iowrite16(adrp[2], ioaddr + MID_1H + 8 * i); - } else { - iowrite16(0xffff, ioaddr + MID_1L + 8 * i); - iowrite16(0xffff, ioaddr + MID_1M + 8 * i); - iowrite16(0xffff, ioaddr + MID_1H + 8 * i); - } + if (i >= MCAST_MAX) + break; + adrp = (u16 *) ha->addr; + iowrite16(adrp[0], ioaddr + MID_1L + 8 * i); + iowrite16(adrp[1], ioaddr + MID_1M + 8 * i); + iowrite16(adrp[2], ioaddr + MID_1H + 8 * i); + i++; + } + while (i < MCAST_MAX) { + iowrite16(0xffff, ioaddr + MID_1L + 8 * i); + iowrite16(0xffff, ioaddr + MID_1M + 8 * i); + iowrite16(0xffff, ioaddr + MID_1H + 8 * i); i++; } } -- cgit v1.2.3 From a93a9798bb28e77112ba9d2e3464b83f8b982ac8 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 20 Sep 2010 15:40:35 -0700 Subject: rose: Fix signedness issues wrt. digi count. [ Upstream commit 9828e6e6e3f19efcb476c567b9999891d051f52f ] Just use explicit casts, since we really can't change the types of structures exported to userspace which have been around for 15 years or so. Reported-by: Dan Rosenberg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/rose/af_rose.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 8e45e76a95f5..d952e7eac188 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -679,7 +679,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1) return -EINVAL; - if (addr->srose_ndigis > ROSE_MAX_DIGIS) + if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS) return -EINVAL; if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) { @@ -739,7 +739,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1) return -EINVAL; - if (addr->srose_ndigis > ROSE_MAX_DIGIS) + if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS) return -EINVAL; /* Source + Destination digis should not exceed ROSE_MAX_DIGIS */ -- cgit v1.2.3 From 44f89254e4ce18795b2b7b9d1f722e0f6ac4711c Mon Sep 17 00:00:00 2001 From: Nagendra Tomar Date: Sat, 2 Oct 2010 23:45:06 +0000 Subject: net: Fix the condition passed to sk_wait_event() [ Upstream commit 482964e56e1320cb7952faa1932d8ecf59c4bf75 ] This patch fixes the condition (3rd arg) passed to sk_wait_event() in sk_stream_wait_memory(). The incorrect check in sk_stream_wait_memory() causes the following soft lockup in tcp_sendmsg() when the global tcp memory pool has exhausted. >>> snip <<< localhost kernel: BUG: soft lockup - CPU#3 stuck for 11s! [sshd:6429] localhost kernel: CPU 3: localhost kernel: RIP: 0010:[sk_stream_wait_memory+0xcd/0x200] [sk_stream_wait_memory+0xcd/0x200] sk_stream_wait_memory+0xcd/0x200 localhost kernel: localhost kernel: Call Trace: localhost kernel: [sk_stream_wait_memory+0x1b1/0x200] sk_stream_wait_memory+0x1b1/0x200 localhost kernel: [] autoremove_wake_function+0x0/0x40 localhost kernel: [ipv6:tcp_sendmsg+0x6e6/0xe90] tcp_sendmsg+0x6e6/0xce0 localhost kernel: [sock_aio_write+0x126/0x140] sock_aio_write+0x126/0x140 localhost kernel: [xfs:do_sync_write+0xf1/0x130] do_sync_write+0xf1/0x130 localhost kernel: [] autoremove_wake_function+0x0/0x40 localhost kernel: [hrtimer_start+0xe3/0x170] hrtimer_start+0xe3/0x170 localhost kernel: [vfs_write+0x185/0x190] vfs_write+0x185/0x190 localhost kernel: [sys_write+0x50/0x90] sys_write+0x50/0x90 localhost kernel: [system_call+0x7e/0x83] system_call+0x7e/0x83 >>> snip <<< What is happening is, that the sk_wait_event() condition passed from sk_stream_wait_memory() evaluates to true for the case of tcp global memory exhaustion. This is because both sk_stream_memory_free() and vm_wait are true which causes sk_wait_event() to *not* call schedule_timeout(). Hence sk_stream_wait_memory() returns immediately to the caller w/o sleeping. This causes the caller to again try allocation, which again fails and again calls sk_stream_wait_memory(), and so on. [ Bug introduced by commit c1cbe4b7ad0bc4b1d98ea708a3fecb7362aa4088 ("[NET]: Avoid atomic xchg() for non-error case") -DaveM ] Signed-off-by: Nagendra Singh Tomar Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/stream.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/core/stream.c b/net/core/stream.c index cc196f42b8d8..9ece62b55761 100644 --- a/net/core/stream.c +++ b/net/core/stream.c @@ -144,10 +144,10 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p) set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); sk->sk_write_pending++; - sk_wait_event(sk, ¤t_timeo, !sk->sk_err && - !(sk->sk_shutdown & SEND_SHUTDOWN) && - sk_stream_memory_free(sk) && - vm_wait); + sk_wait_event(sk, ¤t_timeo, sk->sk_err || + (sk->sk_shutdown & SEND_SHUTDOWN) || + (sk_stream_memory_free(sk) && + !vm_wait)); sk->sk_write_pending--; if (vm_wait) { -- cgit v1.2.3 From 56b8700a1069f66ace7575b9cd104f626379f8cd Mon Sep 17 00:00:00 2001 From: "holt@sgi.com" Date: Wed, 20 Oct 2010 02:03:37 +0000 Subject: Limit sysctl_tcp_mem and sysctl_udp_mem initializers to prevent integer overflows. On a 16TB x86_64 machine, sysctl_tcp_mem[2], sysctl_udp_mem[2], and sysctl_sctp_mem[2] can integer overflow. Set limit such that they are maximized without overflowing. Signed-off-by: Robin Holt To: "David S. Miller" Cc: Willy Tarreau Cc: linux-kernel@vger.kernel.org Cc: netdev@vger.kernel.org Cc: linux-sctp@vger.kernel.org Cc: Alexey Kuznetsov Cc: "Pekka Savola (ipv6)" Cc: James Morris Cc: Hideaki YOSHIFUJI Cc: Patrick McHardy Cc: Vlad Yasevich Cc: Sridhar Samudrala Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp.c | 4 +++- net/ipv4/udp.c | 4 +++- net/sctp/protocol.c | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index c88ca260585d..0e22467e040d 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -3252,12 +3252,14 @@ void __init tcp_init(void) /* Set the pressure threshold to be a fraction of global memory that * is up to 1/2 at 256 MB, decreasing toward zero with the amount of - * memory, with a floor of 128 pages. + * memory, with a floor of 128 pages, and a ceiling that prevents an + * integer overflow. */ nr_pages = totalram_pages - totalhigh_pages; limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); limit = max(limit, 128UL); + limit = min(limit, INT_MAX * 4UL / 3 / 2); sysctl_tcp_mem[0] = limit / 4 * 3; sysctl_tcp_mem[1] = limit; sysctl_tcp_mem[2] = sysctl_tcp_mem[0] * 2; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 434dd6777419..f0fbbba1d203 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -2167,12 +2167,14 @@ void __init udp_init(void) udp_table_init(&udp_table, "UDP"); /* Set the pressure threshold up by the same strategy of TCP. It is a * fraction of global memory that is up to 1/2 at 256 MB, decreasing - * toward zero with the amount of memory, with a floor of 128 pages. + * toward zero with the amount of memory, with a floor of 128 pages, + * and a ceiling that prevents an integer overflow. */ nr_pages = totalram_pages - totalhigh_pages; limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); limit = max(limit, 128UL); + limit = min(limit, INT_MAX * 4UL / 3 / 2); sysctl_udp_mem[0] = limit / 4 * 3; sysctl_udp_mem[1] = limit; sysctl_udp_mem[2] = sysctl_udp_mem[0] * 2; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 182749867c72..b3d890fdf51b 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -1161,7 +1161,8 @@ SCTP_STATIC __init int sctp_init(void) /* Set the pressure threshold to be a fraction of global memory that * is up to 1/2 at 256 MB, decreasing toward zero with the amount of - * memory, with a floor of 128 pages. + * memory, with a floor of 128 pages, and a ceiling that prevents an + * integer overflow. * Note this initalizes the data in sctpv6_prot too * Unabashedly stolen from tcp_init */ @@ -1169,6 +1170,7 @@ SCTP_STATIC __init int sctp_init(void) limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); limit = max(limit, 128UL); + limit = min(limit, INT_MAX * 4UL / 3 / 2); sysctl_sctp_mem[0] = limit / 4 * 3; sysctl_sctp_mem[1] = limit; sysctl_sctp_mem[2] = sysctl_sctp_mem[0] * 2; -- cgit v1.2.3 From 4ba3d9baf1ebfb97ea04384e8b2775744b341268 Mon Sep 17 00:00:00 2001 From: Tom Marshall Date: Mon, 20 Sep 2010 15:42:05 -0700 Subject: tcp: Fix race in tcp_poll [ Upstream commit a4d258036ed9b2a1811c3670c6099203a0f284a0 ] If a RST comes in immediately after checking sk->sk_err, tcp_poll will return POLLIN but not POLLOUT. Fix this by checking sk->sk_err at the end of tcp_poll. Additionally, ensure the correct order of operations on SMP machines with memory barriers. Signed-off-by: Tom Marshall Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp.c | 7 +++++-- net/ipv4/tcp_input.c | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 0e22467e040d..dc6cffa8a9cf 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -388,8 +388,6 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) */ mask = 0; - if (sk->sk_err) - mask = POLLERR; /* * POLLHUP is certainly not done right. But poll() doesn't @@ -459,6 +457,11 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) if (tp->urg_data & TCP_URG_VALID) mask |= POLLPRI; } + /* This barrier is coupled with smp_wmb() in tcp_reset() */ + smp_rmb(); + if (sk->sk_err) + mask |= POLLERR; + return mask; } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 548d575e6cc6..d83b4967cf68 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4041,6 +4041,8 @@ static void tcp_reset(struct sock *sk) default: sk->sk_err = ECONNRESET; } + /* This barrier is coupled with smp_rmb() in tcp_poll() */ + smp_wmb(); if (!sock_flag(sk, SOCK_DEAD)) sk->sk_error_report(sk); -- cgit v1.2.3 From ea912fae3bb8e465497f0f4c8f3dcb3e9057cf06 Mon Sep 17 00:00:00 2001 From: Damian Lukowski Date: Tue, 28 Sep 2010 13:08:32 -0700 Subject: net-2.6: SYN retransmits: Add new parameter to retransmits_timed_out() [ Upstream commit 4d22f7d372f5769c6c0149e427ed6353e2dcfe61 ] Fixes kernel Bugzilla Bug 18952 This patch adds a syn_set parameter to the retransmits_timed_out() routine and updates its callers. If not set, TCP_RTO_MIN is taken as the calculation basis as before. If set, TCP_TIMEOUT_INIT is used instead, so that sysctl_syn_retries represents the actual amount of SYN retransmissions in case no SYNACKs are received when establishing a new connection. Signed-off-by: Damian Lukowski Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_timer.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 7abd922b205b..ebb3dbb86d80 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -136,13 +136,16 @@ static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk) /* This function calculates a "timeout" which is equivalent to the timeout of a * TCP connection after "boundary" unsuccessful, exponentially backed-off - * retransmissions with an initial RTO of TCP_RTO_MIN. + * retransmissions with an initial RTO of TCP_RTO_MIN or TCP_TIMEOUT_INIT if + * syn_set flag is set. */ static bool retransmits_timed_out(struct sock *sk, - unsigned int boundary) + unsigned int boundary, + bool syn_set) { unsigned int timeout, linear_backoff_thresh; unsigned int start_ts; + unsigned int rto_base = syn_set ? TCP_TIMEOUT_INIT : TCP_RTO_MIN; if (!inet_csk(sk)->icsk_retransmits) return false; @@ -152,12 +155,12 @@ static bool retransmits_timed_out(struct sock *sk, else start_ts = tcp_sk(sk)->retrans_stamp; - linear_backoff_thresh = ilog2(TCP_RTO_MAX/TCP_RTO_MIN); + linear_backoff_thresh = ilog2(TCP_RTO_MAX/rto_base); if (boundary <= linear_backoff_thresh) - timeout = ((2 << boundary) - 1) * TCP_RTO_MIN; + timeout = ((2 << boundary) - 1) * rto_base; else - timeout = ((2 << linear_backoff_thresh) - 1) * TCP_RTO_MIN + + timeout = ((2 << linear_backoff_thresh) - 1) * rto_base + (boundary - linear_backoff_thresh) * TCP_RTO_MAX; return (tcp_time_stamp - start_ts) >= timeout; @@ -168,14 +171,15 @@ static int tcp_write_timeout(struct sock *sk) { struct inet_connection_sock *icsk = inet_csk(sk); int retry_until; - bool do_reset; + bool do_reset, syn_set = 0; if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { if (icsk->icsk_retransmits) dst_negative_advice(sk); retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries; + syn_set = 1; } else { - if (retransmits_timed_out(sk, sysctl_tcp_retries1)) { + if (retransmits_timed_out(sk, sysctl_tcp_retries1, 0)) { /* Black hole detection */ tcp_mtu_probing(icsk, sk); @@ -188,14 +192,14 @@ static int tcp_write_timeout(struct sock *sk) retry_until = tcp_orphan_retries(sk, alive); do_reset = alive || - !retransmits_timed_out(sk, retry_until); + !retransmits_timed_out(sk, retry_until, 0); if (tcp_out_of_resources(sk, do_reset)) return 1; } } - if (retransmits_timed_out(sk, retry_until)) { + if (retransmits_timed_out(sk, retry_until, syn_set)) { /* Has it gone just too far? */ tcp_write_err(sk); return 1; @@ -437,7 +441,7 @@ out_reset_timer: icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX); } inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX); - if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1)) + if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1, 0)) __sk_dst_reset(sk); out:; -- cgit v1.2.3 From 4ac86dc5d9f1407e94253e29b7b6c57517f9abae Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 21 Oct 2010 01:06:15 +0000 Subject: Revert c6537d6742985da1fbf12ae26cde6a096fd35b5c [ Upstream commit 8c974438085d2c81b006daeaab8801eedbd19758 ] Backout the tipc changes to the flags int he subscription message. These changees, while reasonable on the surface, interefere with user space ABI compatibility which is a no-no. This was part of the changes to fix the endianess issues in the TIPC protocol, which would be really nice to do but we need to do so in a way that is backwards compatible with user space. Signed-off-by: Neil Horman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/tipc.h | 30 ++++++++++++++++++------------ net/tipc/subscr.c | 15 +++++---------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/include/linux/tipc.h b/include/linux/tipc.h index 181c8d0e6f73..d10614b29d59 100644 --- a/include/linux/tipc.h +++ b/include/linux/tipc.h @@ -127,17 +127,23 @@ static inline unsigned int tipc_node(__u32 addr) * TIPC topology subscription service definitions */ -#define TIPC_SUB_SERVICE 0x00 /* Filter for service availability */ -#define TIPC_SUB_PORTS 0x01 /* Filter for port availability */ -#define TIPC_SUB_CANCEL 0x04 /* Cancel a subscription */ +#define TIPC_SUB_PORTS 0x01 /* filter for port availability */ +#define TIPC_SUB_SERVICE 0x02 /* filter for service availability */ +#define TIPC_SUB_CANCEL 0x04 /* cancel a subscription */ +#if 0 +/* The following filter options are not currently implemented */ +#define TIPC_SUB_NO_BIND_EVTS 0x04 /* filter out "publish" events */ +#define TIPC_SUB_NO_UNBIND_EVTS 0x08 /* filter out "withdraw" events */ +#define TIPC_SUB_SINGLE_EVT 0x10 /* expire after first event */ +#endif #define TIPC_WAIT_FOREVER ~0 /* timeout for permanent subscription */ struct tipc_subscr { - struct tipc_name_seq seq; /* NBO. Name sequence of interest */ - __u32 timeout; /* NBO. Subscription duration (in ms) */ - __u32 filter; /* NBO. Bitmask of filter options */ - char usr_handle[8]; /* Opaque. Available for subscriber use */ + struct tipc_name_seq seq; /* name sequence of interest */ + __u32 timeout; /* subscription duration (in ms) */ + __u32 filter; /* bitmask of filter options */ + char usr_handle[8]; /* available for subscriber use */ }; #define TIPC_PUBLISHED 1 /* publication event */ @@ -145,11 +151,11 @@ struct tipc_subscr { #define TIPC_SUBSCR_TIMEOUT 3 /* subscription timeout event */ struct tipc_event { - __u32 event; /* NBO. Event type, as defined above */ - __u32 found_lower; /* NBO. Matching name seq instances */ - __u32 found_upper; /* " " " " " */ - struct tipc_portid port; /* NBO. Associated port */ - struct tipc_subscr s; /* Original, associated subscription */ + __u32 event; /* event type */ + __u32 found_lower; /* matching name seq instances */ + __u32 found_upper; /* " " " " */ + struct tipc_portid port; /* associated port */ + struct tipc_subscr s; /* associated subscription */ }; /* diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index ab6eab4c45e2..ff123e56114a 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -274,7 +274,7 @@ static void subscr_cancel(struct tipc_subscr *s, { struct subscription *sub; struct subscription *sub_temp; - __u32 type, lower, upper, timeout, filter; + __u32 type, lower, upper; int found = 0; /* Find first matching subscription, exit if not found */ @@ -282,18 +282,12 @@ static void subscr_cancel(struct tipc_subscr *s, type = ntohl(s->seq.type); lower = ntohl(s->seq.lower); upper = ntohl(s->seq.upper); - timeout = ntohl(s->timeout); - filter = ntohl(s->filter) & ~TIPC_SUB_CANCEL; list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, subscription_list) { if ((type == sub->seq.type) && (lower == sub->seq.lower) && - (upper == sub->seq.upper) && - (timeout == sub->timeout) && - (filter == sub->filter) && - !memcmp(s->usr_handle,sub->evt.s.usr_handle, - sizeof(s->usr_handle)) ){ + (upper == sub->seq.upper)) { found = 1; break; } @@ -310,7 +304,7 @@ static void subscr_cancel(struct tipc_subscr *s, k_term_timer(&sub->timer); spin_lock_bh(subscriber->lock); } - dbg("Cancel: removing sub %u,%u,%u from subscriber %p list\n", + dbg("Cancel: removing sub %u,%u,%u from subscriber %x list\n", sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); subscr_del(sub); } @@ -358,7 +352,8 @@ static struct subscription *subscr_subscribe(struct tipc_subscr *s, sub->seq.upper = ntohl(s->seq.upper); sub->timeout = ntohl(s->timeout); sub->filter = ntohl(s->filter); - if ((sub->filter && (sub->filter != TIPC_SUB_PORTS)) || + if ((!(sub->filter & TIPC_SUB_PORTS) == + !(sub->filter & TIPC_SUB_SERVICE)) || (sub->seq.lower > sub->seq.upper)) { warn("Subscription rejected, illegal request\n"); kfree(sub); -- cgit v1.2.3 From a3c1c5704f66741f3249926b31cc4a201b1faeda Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 21 Oct 2010 01:06:16 +0000 Subject: Revert d88dca79d3852a3623f606f781e013d61486828a [ Upstream commit db5a753bf198ef7a50e17d2ff358adf37efe8648 ] TIPC needs to have its endianess issues fixed. Unfortunately, the format of a subscriber message is passed in directly from user space, so requiring this message to be in network byte order breaks user space ABI. Revert this change until such time as we can determine how to do this in a backwards compatible manner. Signed-off-by: Neil Horman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/tipc/subscr.c | 57 ++++++++++++++++++++++++++++++++++--------------------- net/tipc/subscr.h | 2 ++ 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index ff123e56114a..ac91f0dfa144 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -75,6 +75,19 @@ struct top_srv { static struct top_srv topsrv = { 0 }; +/** + * htohl - convert value to endianness used by destination + * @in: value to convert + * @swap: non-zero if endianness must be reversed + * + * Returns converted value + */ + +static u32 htohl(u32 in, int swap) +{ + return swap ? swab32(in) : in; +} + /** * subscr_send_event - send a message containing a tipc_event to the subscriber * @@ -94,11 +107,11 @@ static void subscr_send_event(struct subscription *sub, msg_sect.iov_base = (void *)&sub->evt; msg_sect.iov_len = sizeof(struct tipc_event); - sub->evt.event = htonl(event); - sub->evt.found_lower = htonl(found_lower); - sub->evt.found_upper = htonl(found_upper); - sub->evt.port.ref = htonl(port_ref); - sub->evt.port.node = htonl(node); + sub->evt.event = htohl(event, sub->swap); + sub->evt.found_lower = htohl(found_lower, sub->swap); + sub->evt.found_upper = htohl(found_upper, sub->swap); + sub->evt.port.ref = htohl(port_ref, sub->swap); + sub->evt.port.node = htohl(node, sub->swap); tipc_send(sub->server_ref, 1, &msg_sect); } @@ -274,23 +287,16 @@ static void subscr_cancel(struct tipc_subscr *s, { struct subscription *sub; struct subscription *sub_temp; - __u32 type, lower, upper; int found = 0; /* Find first matching subscription, exit if not found */ - type = ntohl(s->seq.type); - lower = ntohl(s->seq.lower); - upper = ntohl(s->seq.upper); - list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, subscription_list) { - if ((type == sub->seq.type) && - (lower == sub->seq.lower) && - (upper == sub->seq.upper)) { - found = 1; - break; - } + if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) { + found = 1; + break; + } } if (!found) return; @@ -319,10 +325,16 @@ static struct subscription *subscr_subscribe(struct tipc_subscr *s, struct subscriber *subscriber) { struct subscription *sub; + int swap; + + /* Determine subscriber's endianness */ + + swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE)); /* Detect & process a subscription cancellation request */ - if (ntohl(s->filter) & TIPC_SUB_CANCEL) { + if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { + s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); subscr_cancel(s, subscriber); return NULL; } @@ -347,11 +359,11 @@ static struct subscription *subscr_subscribe(struct tipc_subscr *s, /* Initialize subscription object */ - sub->seq.type = ntohl(s->seq.type); - sub->seq.lower = ntohl(s->seq.lower); - sub->seq.upper = ntohl(s->seq.upper); - sub->timeout = ntohl(s->timeout); - sub->filter = ntohl(s->filter); + sub->seq.type = htohl(s->seq.type, swap); + sub->seq.lower = htohl(s->seq.lower, swap); + sub->seq.upper = htohl(s->seq.upper, swap); + sub->timeout = htohl(s->timeout, swap); + sub->filter = htohl(s->filter, swap); if ((!(sub->filter & TIPC_SUB_PORTS) == !(sub->filter & TIPC_SUB_SERVICE)) || (sub->seq.lower > sub->seq.upper)) { @@ -364,6 +376,7 @@ static struct subscription *subscr_subscribe(struct tipc_subscr *s, INIT_LIST_HEAD(&sub->nameseq_list); list_add(&sub->subscription_list, &subscriber->subscription_list); sub->server_ref = subscriber->port_ref; + sub->swap = swap; memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); atomic_inc(&topsrv.subscription_count); if (sub->timeout != TIPC_WAIT_FOREVER) { diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index c20f496d95b2..45d89bf4d202 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h @@ -53,6 +53,7 @@ typedef void (*tipc_subscr_event) (struct subscription *sub, * @nameseq_list: adjacent subscriptions in name sequence's subscription list * @subscription_list: adjacent subscriptions in subscriber's subscription list * @server_ref: object reference of server port associated with subscription + * @swap: indicates if subscriber uses opposite endianness in its messages * @evt: template for events generated by subscription */ @@ -65,6 +66,7 @@ struct subscription { struct list_head nameseq_list; struct list_head subscription_list; u32 server_ref; + int swap; struct tipc_event evt; }; -- cgit v1.2.3 From 3f266b04185de51d8e6446eb1fccec3b5e7ce575 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 29 Sep 2010 13:23:09 -0700 Subject: net: add a recursion limit in xmit path [ Upstream commits 745e20f1b626b1be4b100af5d4bf7b3439392f8f and 11a766ce915fc9f8663714eac6d59239388534ea ] As tunnel devices are going to be lockless, we need to make sure a misconfigured machine wont enter an infinite loop. Add a percpu variable, and limit to three the number of stacked xmits. Reported-by: Jesse Gross Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 95cc48618043..ca47a64929ff 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2110,6 +2110,9 @@ static inline int skb_needs_linearize(struct sk_buff *skb, illegal_highdma(dev, skb))); } +static DEFINE_PER_CPU(int, xmit_recursion); +#define RECURSION_LIMIT 10 + /** * dev_queue_xmit - transmit a buffer * @skb: buffer to transmit @@ -2194,10 +2197,15 @@ gso: if (txq->xmit_lock_owner != cpu) { + if (__this_cpu_read(xmit_recursion) > RECURSION_LIMIT) + goto recursion_alert; + HARD_TX_LOCK(dev, txq, cpu); if (!netif_tx_queue_stopped(txq)) { + __this_cpu_inc(xmit_recursion); rc = dev_hard_start_xmit(skb, dev, txq); + __this_cpu_dec(xmit_recursion); if (dev_xmit_complete(rc)) { HARD_TX_UNLOCK(dev, txq); goto out; @@ -2209,7 +2217,9 @@ gso: "queue packet!\n", dev->name); } else { /* Recursion is detected! It is possible, - * unfortunately */ + * unfortunately + */ +recursion_alert: if (net_ratelimit()) printk(KERN_CRIT "Dead loop on virtual device " "%s, fix it urgently!\n", dev->name); -- cgit v1.2.3 From e26158f99c3c79181eb3e314e898079565cc75fd Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Thu, 21 Oct 2010 04:06:29 -0700 Subject: net/core: Allow tagged VLAN packets to flow through VETH devices. [ Upstream commit d2ed817766987fd05e69b7da65d4861b38f1aa2a ] When there are VLANs on a VETH device, the packets being transmitted through the VETH device may be 4 bytes bigger than MTU. A check in dev_forward_skb did not take this into account and so dropped these packets. This patch is needed at least as far back as 2.6.34.7 and should be considered for -stable. Signed-off-by: Ben Greear Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index ca47a64929ff..a7054e88eb67 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1491,7 +1491,7 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) nf_reset(skb); if (!(dev->flags & IFF_UP) || - (skb->len > (dev->mtu + dev->hard_header_len))) { + (skb->len > (dev->mtu + dev->hard_header_len + VLAN_HLEN))) { kfree_skb(skb); return NET_RX_DROP; } -- cgit v1.2.3 From badaad1d7392eebf646b2e2d4dfe2586e40a8f18 Mon Sep 17 00:00:00 2001 From: Ulrich Weber Date: Wed, 22 Sep 2010 06:45:11 +0000 Subject: xfrm4: strip ECN bits from tos field [ Upstream commit 94e2238969e89f5112297ad2a00103089dde7e8f ] otherwise ECT(1) bit will get interpreted as RTO_ONLINK and routing will fail with XfrmOutBundleGenError. Signed-off-by: Ulrich Weber Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/xfrm4_policy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 23883a48ebfb..ce1e1b5fdd50 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -61,7 +61,7 @@ static int xfrm4_get_saddr(struct net *net, static int xfrm4_get_tos(struct flowi *fl) { - return fl->fl4_tos; + return IPTOS_RT_MASK & fl->fl4_tos; /* Strip ECN bits */ } static int xfrm4_init_path(struct xfrm_dst *path, struct dst_entry *dst, -- cgit v1.2.3 From e0b20e1140f0a2b691cffd28c7ac2a29d59b96ee Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 12 Oct 2010 11:40:08 -0400 Subject: secmark: do not return early if there was no error commit 15714f7b58011cf3948cab2988abea560240c74f upstream. Commit 4a5a5c73 attempted to pass decent error messages back to userspace for netfilter errors. In xt_SECMARK.c however the patch screwed up and returned on 0 (aka no error) early and didn't finish setting up secmark. This results in a kernel BUG if you use SECMARK. Signed-off-by: Eric Paris Acked-by: Paul Moore Signed-off-by: James Morris Signed-off-by: Greg Kroah-Hartman --- net/netfilter/xt_SECMARK.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c index 23b2d6c486b5..364ad1600129 100644 --- a/net/netfilter/xt_SECMARK.c +++ b/net/netfilter/xt_SECMARK.c @@ -101,7 +101,7 @@ static int secmark_tg_check(const struct xt_tgchk_param *par) switch (info->mode) { case SECMARK_MODE_SEL: err = checkentry_selinux(info); - if (err <= 0) + if (err) return err; break; -- cgit v1.2.3 From 2a883ff9199bf4cfb8b5d37e4907662d3273ce97 Mon Sep 17 00:00:00 2001 From: Mac Lin Date: Sun, 14 Nov 2010 22:17:23 +0000 Subject: ARM: cns3xxx: Fixup the missing second parameter to addruart macro to allow them to build. It can't be merged into Linus' tree because this file has already been changed in incompatible ways. Fixup the missing second parameter to addruart macro to allow them to build, according to to commit 0e17226f7cd289504724466f4298abc9bdfca3fe. Enabling DEBUG in head.S would cause: rch/arm/boot/compressed/head.S: Assembler messages: arch/arm/boot/compressed/head.S:1037: Error: too many positional arguments arch/arm/boot/compressed/head.S:1055: Error: too many positional arguments Signed-off-by: Mac Lin Acked-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-cns3xxx/include/mach/debug-macro.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-cns3xxx/include/mach/debug-macro.S b/arch/arm/mach-cns3xxx/include/mach/debug-macro.S index d16ce7eb00e9..9b50442d4b9b 100644 --- a/arch/arm/mach-cns3xxx/include/mach/debug-macro.S +++ b/arch/arm/mach-cns3xxx/include/mach/debug-macro.S @@ -10,7 +10,7 @@ * published by the Free Software Foundation. */ - .macro addruart,rx + .macro addruart,rx,rtmp mrc p15, 0, \rx, c1, c0 tst \rx, #1 @ MMU enabled? moveq \rx, #0x10000000 -- cgit v1.2.3 From 29d818b400cb9b0a221e1d7d8682e264f24b772e Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Tue, 26 Oct 2010 14:21:15 -0700 Subject: sgi-xp: incoming XPC channel messages can come in after the channel's partition structures have been torn down commit 09358972bff5ce99de496bbba97c85d417b3c054 upstream. Under some workloads, some channel messages have been observed being delayed on the sending side past the point where the receiving side has been able to tear down its partition structures. This condition is already detected in xpc_handle_activate_IRQ_uv(), but that information is not given to xpc_handle_activate_mq_msg_uv(). As a result, xpc_handle_activate_mq_msg_uv() assumes the structures still exist and references them, causing a NULL-pointer deref. Signed-off-by: Robin Holt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/misc/sgi-xp/xpc_uv.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index 1f59ee2226ca..17bbacb1b4b1 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c @@ -417,6 +417,7 @@ xpc_process_activate_IRQ_rcvd_uv(void) static void xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, struct xpc_activate_mq_msghdr_uv *msg_hdr, + int part_setup, int *wakeup_hb_checker) { unsigned long irq_flags; @@ -481,6 +482,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV: { struct xpc_activate_mq_msg_chctl_closerequest_uv *msg; + if (!part_setup) + break; + msg = container_of(msg_hdr, struct xpc_activate_mq_msg_chctl_closerequest_uv, hdr); @@ -497,6 +501,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV: { struct xpc_activate_mq_msg_chctl_closereply_uv *msg; + if (!part_setup) + break; + msg = container_of(msg_hdr, struct xpc_activate_mq_msg_chctl_closereply_uv, hdr); @@ -511,6 +518,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV: { struct xpc_activate_mq_msg_chctl_openrequest_uv *msg; + if (!part_setup) + break; + msg = container_of(msg_hdr, struct xpc_activate_mq_msg_chctl_openrequest_uv, hdr); @@ -528,6 +538,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV: { struct xpc_activate_mq_msg_chctl_openreply_uv *msg; + if (!part_setup) + break; + msg = container_of(msg_hdr, struct xpc_activate_mq_msg_chctl_openreply_uv, hdr); args = &part->remote_openclose_args[msg->ch_number]; @@ -545,6 +558,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV: { struct xpc_activate_mq_msg_chctl_opencomplete_uv *msg; + if (!part_setup) + break; + msg = container_of(msg_hdr, struct xpc_activate_mq_msg_chctl_opencomplete_uv, hdr); spin_lock_irqsave(&part->chctl_lock, irq_flags); @@ -621,6 +637,7 @@ xpc_handle_activate_IRQ_uv(int irq, void *dev_id) part_referenced = xpc_part_ref(part); xpc_handle_activate_mq_msg_uv(part, msg_hdr, + part_referenced, &wakeup_hb_checker); if (part_referenced) xpc_part_deref(part); -- cgit v1.2.3 From e3a8550880f75c4ca34ac8009b8d8190d36d5c0b Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Mon, 5 Jul 2010 14:18:27 +0000 Subject: isdn: avoid calling tty_ldisc_flush() in atomic context commit bc10f96757bd6ab3721510df8defa8f21c32f974 upstream. Remove the call to tty_ldisc_flush() from the RESULT_NO_CARRIER branch of isdn_tty_modem_result(), as already proposed in commit 00409bb045887ec5e7b9e351bc080c38ab6bfd33. This avoids a "sleeping function called from invalid context" BUG when the hardware driver calls the statcallb() callback with command==ISDN_STAT_DHUP in atomic context, which in turn calls isdn_tty_modem_result(RESULT_NO_CARRIER, ~), and from there, tty_ldisc_flush() which may sleep. Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/i4l/isdn_tty.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index fc8454d2eea5..51dc60da333b 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -2636,12 +2636,6 @@ isdn_tty_modem_result(int code, modem_info * info) if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) { return; } -#ifdef CONFIG_ISDN_AUDIO - if ( !info->vonline ) - tty_ldisc_flush(info->tty); -#else - tty_ldisc_flush(info->tty); -#endif if ((info->flags & ISDN_ASYNC_CHECK_CD) && (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) && (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) { -- cgit v1.2.3 From 4c3c3a114f20eb79e0fd09fba6dd13a373a73ced Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 26 Aug 2010 14:31:30 +0300 Subject: KVM: x86 emulator: fix regression with cmpxchg8b on i386 hosts commit 16518d5ada690643453eb0aef3cc7841d3623c2d upstream. operand::val and operand::orig_val are 32-bit on i386, whereas cmpxchg8b operands are 64-bit. Fix by adding val64 and orig_val64 union members to struct operand, and using them where needed. Signed-off-by: Avi Kivity Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/kvm_emulate.h | 10 +++++++++- arch/x86/kvm/emulate.c | 9 ++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index 0b2729bf2070..50de7b4b2db1 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h @@ -143,7 +143,15 @@ struct x86_emulate_ops { struct operand { enum { OP_REG, OP_MEM, OP_IMM, OP_NONE } type; unsigned int bytes; - unsigned long val, orig_val, *ptr; + union { + unsigned long orig_val; + u64 orig_val64; + }; + unsigned long *ptr; + union { + unsigned long val; + u64 val64; + }; }; struct fetch_cache { diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 715a7fa42be6..582c8fcad2e1 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -1712,17 +1712,16 @@ static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) { struct decode_cache *c = &ctxt->decode; - u64 old = c->dst.orig_val; + u64 old = c->dst.orig_val64; if (((u32) (old >> 0) != (u32) c->regs[VCPU_REGS_RAX]) || ((u32) (old >> 32) != (u32) c->regs[VCPU_REGS_RDX])) { - c->regs[VCPU_REGS_RAX] = (u32) (old >> 0); c->regs[VCPU_REGS_RDX] = (u32) (old >> 32); ctxt->eflags &= ~EFLG_ZF; } else { - c->dst.val = ((u64)c->regs[VCPU_REGS_RCX] << 32) | - (u32) c->regs[VCPU_REGS_RBX]; + c->dst.val64 = ((u64)c->regs[VCPU_REGS_RCX] << 32) | + (u32) c->regs[VCPU_REGS_RBX]; ctxt->eflags |= EFLG_ZF; } @@ -2535,7 +2534,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) ctxt->vcpu); if (rc != X86EMUL_CONTINUE) goto done; - c->src.orig_val = c->src.val; + c->src.orig_val64 = c->src.val64; } if (c->src2.type == OP_MEM) { -- cgit v1.2.3 From 512ac859f60d61374783e276f8fb7861a9d1d0b9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 22 Nov 2010 11:01:26 -0800 Subject: Linux 2.6.35.9 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a15479163a1c..90ba786b757c 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 35 -EXTRAVERSION = .8 +EXTRAVERSION = .9 NAME = Yokohama # *DOCUMENTATION* -- cgit v1.2.3 From 97d388bb0a4d7e5acc7274645382adac50260096 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Wed, 13 Oct 2010 21:18:03 +0200 Subject: block: Ensure physical block size is unsigned int commit 892b6f90db81cccb723d5d92f4fddc2d68b206e1 upstream. Physical block size was declared unsigned int to accomodate the maximum size reported by READ CAPACITY(16). Make sure we use the right type in the related functions. Signed-off-by: Martin K. Petersen Acked-by: Mike Snitzer Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- block/blk-settings.c | 2 +- include/linux/blkdev.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/block/blk-settings.c b/block/blk-settings.c index f5ed5a1187ba..3430c1fc9df7 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -326,7 +326,7 @@ EXPORT_SYMBOL(blk_queue_logical_block_size); * hardware can operate on without reverting to read-modify-write * operations. */ -void blk_queue_physical_block_size(struct request_queue *q, unsigned short size) +void blk_queue_physical_block_size(struct request_queue *q, unsigned int size) { q->limits.physical_block_size = size; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 09a840264d6f..7b35803a56cc 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -936,7 +936,7 @@ extern void blk_queue_max_segment_size(struct request_queue *, unsigned int); extern void blk_queue_max_discard_sectors(struct request_queue *q, unsigned int max_discard_sectors); extern void blk_queue_logical_block_size(struct request_queue *, unsigned short); -extern void blk_queue_physical_block_size(struct request_queue *, unsigned short); +extern void blk_queue_physical_block_size(struct request_queue *, unsigned int); extern void blk_queue_alignment_offset(struct request_queue *q, unsigned int alignment); extern void blk_limits_io_min(struct queue_limits *limits, unsigned int min); @@ -1086,7 +1086,7 @@ static inline unsigned int queue_physical_block_size(struct request_queue *q) return q->limits.physical_block_size; } -static inline int bdev_physical_block_size(struct block_device *bdev) +static inline unsigned int bdev_physical_block_size(struct block_device *bdev) { return queue_physical_block_size(bdev_get_queue(bdev)); } -- cgit v1.2.3 From 381709fcb98acf7803be64ceab5e49e2fc0dbbdb Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 16 Sep 2010 20:36:36 +0200 Subject: block: Fix race during disk initialization commit 01ea50638bc04ca5259f5711fcdedefcdde1cf43 upstream. When a new disk is being discovered, add_disk() first ties the bdev to gendisk (via register_disk()->blkdev_get()) and only after that calls bdi_register_bdev(). Because register_disk() also creates disk's kobject, it can happen that userspace manages to open and modify the device's data (or inode) before its BDI is properly initialized leading to a warning in __mark_inode_dirty(). Fix the problem by registering BDI early enough. This patch addresses https://bugzilla.kernel.org/show_bug.cgi?id=16312 Reported-by: Larry Finger Signed-off-by: Jan Kara Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- block/genhd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 59a2db6fecef..315afd2f2088 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -541,13 +541,15 @@ void add_disk(struct gendisk *disk) disk->major = MAJOR(devt); disk->first_minor = MINOR(devt); + /* Register BDI before referencing it from bdev */ + bdi = &disk->queue->backing_dev_info; + bdi_register_dev(bdi, disk_devt(disk)); + blk_register_region(disk_devt(disk), disk->minors, NULL, exact_match, exact_lock, disk); register_disk(disk); blk_register_queue(disk); - bdi = &disk->queue->backing_dev_info; - bdi_register_dev(bdi, disk_devt(disk)); retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj, "bdi"); WARN_ON(retval); -- cgit v1.2.3 From 6033d45c07fc80b4c70899b081a3c11f5ee9f6ea Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 29 Oct 2010 11:46:56 -0600 Subject: block: limit vec count in bio_kmalloc() and bio_alloc_map_data() commit f3f63c1c28bc861a931fac283b5bc3585efb8967 upstream. Reported-by: Dan Rosenberg Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/bio.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/bio.c b/fs/bio.c index e7bf6ca64dcf..75ea4c3b1d10 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -370,6 +370,9 @@ struct bio *bio_kmalloc(gfp_t gfp_mask, int nr_iovecs) { struct bio *bio; + if (nr_iovecs > UIO_MAXIOV) + return NULL; + bio = kmalloc(sizeof(struct bio) + nr_iovecs * sizeof(struct bio_vec), gfp_mask); if (unlikely(!bio)) @@ -697,8 +700,12 @@ static void bio_free_map_data(struct bio_map_data *bmd) static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count, gfp_t gfp_mask) { - struct bio_map_data *bmd = kmalloc(sizeof(*bmd), gfp_mask); + struct bio_map_data *bmd; + + if (iov_count > UIO_MAXIOV) + return NULL; + bmd = kmalloc(sizeof(*bmd), gfp_mask); if (!bmd) return NULL; -- cgit v1.2.3 From 116ad352e4fefafd5d6abc819691e61603604bee Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 29 Oct 2010 11:31:42 -0600 Subject: block: take care not to overflow when calculating total iov length commit 9f864c80913467312c7b8690e41fb5ebd1b50e92 upstream. Reported-by: Dan Rosenberg Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- block/scsi_ioctl.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index a8b5a10eb5b0..4f4230b79bb6 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -321,33 +321,47 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk, if (hdr->iovec_count) { const int size = sizeof(struct sg_iovec) * hdr->iovec_count; size_t iov_data_len; - struct sg_iovec *iov; + struct sg_iovec *sg_iov; + struct iovec *iov; + int i; - iov = kmalloc(size, GFP_KERNEL); - if (!iov) { + sg_iov = kmalloc(size, GFP_KERNEL); + if (!sg_iov) { ret = -ENOMEM; goto out; } - if (copy_from_user(iov, hdr->dxferp, size)) { - kfree(iov); + if (copy_from_user(sg_iov, hdr->dxferp, size)) { + kfree(sg_iov); ret = -EFAULT; goto out; } + /* + * Sum up the vecs, making sure they don't overflow + */ + iov = (struct iovec *) sg_iov; + iov_data_len = 0; + for (i = 0; i < hdr->iovec_count; i++) { + if (iov_data_len + iov[i].iov_len < iov_data_len) { + kfree(sg_iov); + ret = -EINVAL; + goto out; + } + iov_data_len += iov[i].iov_len; + } + /* SG_IO howto says that the shorter of the two wins */ - iov_data_len = iov_length((struct iovec *)iov, - hdr->iovec_count); if (hdr->dxfer_len < iov_data_len) { - hdr->iovec_count = iov_shorten((struct iovec *)iov, + hdr->iovec_count = iov_shorten(iov, hdr->iovec_count, hdr->dxfer_len); iov_data_len = hdr->dxfer_len; } - ret = blk_rq_map_user_iov(q, rq, NULL, iov, hdr->iovec_count, + ret = blk_rq_map_user_iov(q, rq, NULL, sg_iov, hdr->iovec_count, iov_data_len, GFP_KERNEL); - kfree(iov); + kfree(sg_iov); } else if (hdr->dxfer_len) ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len, GFP_KERNEL); -- cgit v1.2.3 From e978df456e01ff5412c29e6fef5dd47960867476 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 29 Oct 2010 08:10:18 -0600 Subject: block: check for proper length of iov entries in blk_rq_map_user_iov() commit 9284bcf4e335e5f18a8bc7b26461c33ab60d0689 upstream. Ensure that we pass down properly validated iov segments before calling into the mapping or copy functions. Reported-by: Dan Rosenberg Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- block/blk-map.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/block/blk-map.c b/block/blk-map.c index 9083cf0180cc..30a7e5158930 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -205,6 +205,8 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, unaligned = 1; break; } + if (!iov[i].iov_len) + return -EINVAL; } if (unaligned || (q->dma_pad_mask & len) || map_data) -- cgit v1.2.3 From 377628f218e00919da873e51cd3b8685ed6f107a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 2 Nov 2010 05:26:48 +0000 Subject: drm/radeon/kms: don't disable shared encoders on pre-DCE3 display blocks commit a0ae5864d42b41c411368bd689462bf063c029c8 upstream. The A/B links aren't independantly useable on these blocks so when we disable the encoders, make sure to only disable the encoder when there is no connector using it. Should fix: https://bugs.freedesktop.org/show_bug.cgi?id=18564 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/radeon_encoders.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index e0b30b264c28..68a3d79a73d4 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1545,6 +1545,23 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig; + + /* check for pre-DCE3 cards with shared encoders; + * can't really use the links individually, so don't disable + * the encoder if it's in use by another connector + */ + if (!ASIC_IS_DCE3(rdev)) { + struct drm_encoder *other_encoder; + struct radeon_encoder *other_radeon_encoder; + + list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) { + other_radeon_encoder = to_radeon_encoder(other_encoder); + if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) && + drm_helper_encoder_in_use(other_encoder)) + goto disable_done; + } + } + radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); switch (radeon_encoder->encoder_id) { @@ -1584,6 +1601,7 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) break; } +disable_done: if (radeon_encoder_is_digital(encoder)) { if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) r600_hdmi_disable(encoder); -- cgit v1.2.3 From 4e331654d0cb8433659b05c080ea48ec79799aa5 Mon Sep 17 00:00:00 2001 From: Guo-Fu Tseng Date: Mon, 18 Oct 2010 14:10:40 +0000 Subject: jme: Fix PHY power-off error commit c8a8684d5cfb0f110a962c93586630c0bf91ebc1 upstream. Adding phy_on in opposition to phy_off. Signed-off-by: Guo-Fu Tseng Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/jme.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/net/jme.c b/drivers/net/jme.c index 99f24f5cac53..f0643ac4aff1 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -1575,6 +1575,16 @@ jme_free_irq(struct jme_adapter *jme) } } +static inline void +jme_phy_on(struct jme_adapter *jme) +{ + u32 bmcr; + + bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); + bmcr &= ~BMCR_PDOWN; + jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); +} + static int jme_open(struct net_device *netdev) { @@ -1595,10 +1605,12 @@ jme_open(struct net_device *netdev) jme_start_irq(jme); - if (test_bit(JME_FLAG_SSET, &jme->flags)) + if (test_bit(JME_FLAG_SSET, &jme->flags)) { + jme_phy_on(jme); jme_set_settings(netdev, &jme->old_ecmd); - else + } else { jme_reset_phy_processor(jme); + } jme_reset_link(jme); @@ -3006,10 +3018,12 @@ jme_resume(struct pci_dev *pdev) jme_clear_pm(jme); pci_restore_state(pdev); - if (test_bit(JME_FLAG_SSET, &jme->flags)) + if (test_bit(JME_FLAG_SSET, &jme->flags)) { + jme_phy_on(jme); jme_set_settings(netdev, &jme->old_ecmd); - else + } else { jme_reset_phy_processor(jme); + } jme_start_irq(jme); netif_device_attach(netdev); -- cgit v1.2.3 From c71b988600389db6b35e924382b93644baebf25d Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 11 Oct 2010 01:17:56 +0200 Subject: irda: Fix parameter extraction stack overflow commit efc463eb508798da4243625b08c7396462cabf9f upstream. Reported-by: Ilja Van Sprundel Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/irda/parameters.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/irda/parameters.c b/net/irda/parameters.c index fc1a20565e2d..71cd38c1a67f 100644 --- a/net/irda/parameters.c +++ b/net/irda/parameters.c @@ -298,6 +298,8 @@ static int irda_extract_string(void *self, __u8 *buf, int len, __u8 pi, p.pi = pi; /* In case handler needs to know */ p.pl = buf[1]; /* Extract length of value */ + if (p.pl > 32) + p.pl = 32; IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d\n", __func__, p.pi, p.pl); @@ -318,7 +320,7 @@ static int irda_extract_string(void *self, __u8 *buf, int len, __u8 pi, (__u8) str[0], (__u8) str[1]); /* Null terminate string */ - str[p.pl+1] = '\0'; + str[p.pl] = '\0'; p.pv.c = str; /* Handler will need to take a copy */ -- cgit v1.2.3 From 207b45e2615ea1bca44e6efcda22f5d01e66f3f0 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 6 Oct 2010 01:03:12 +0200 Subject: irda: Fix heap memory corruption in iriap.c commit 37f9fc452d138dfc4da2ee1ce5ae85094efc3606 upstream. While parsing the GetValuebyClass command frame, we could potentially write passed the skb->data pointer. Reported-by: Ilja Van Sprundel Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/irda/iriap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/irda/iriap.c b/net/irda/iriap.c index fce364c6c71a..5b743bdd89ba 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c @@ -502,7 +502,8 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self, IRDA_DEBUG(4, "%s(), strlen=%d\n", __func__, value_len); /* Make sure the string is null-terminated */ - fp[n+value_len] = 0x00; + if (n + value_len < skb->len) + fp[n + value_len] = 0x00; IRDA_DEBUG(4, "Got string %s\n", fp+n); /* Will truncate to IAS_MAX_STRING bytes */ -- cgit v1.2.3 From 8c344624d82e34d805d9250b942158f652e9ac75 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 6 Oct 2010 21:18:04 +0200 Subject: cfg80211: fix BSS double-unlinking commit 3207390a8b58bfc1335750f91cf6783c48ca19ca upstream. When multiple interfaces are actively trying to associate with the same BSS, they may both find that the BSS isn't there and then try to unlink it. This can cause errors since the unlinking code can't currently deal with items that have already been unlinked. Normally this doesn't happen as most people don't try to use multiple station interfaces that associate at the same time too. Fix this by using the list entry as a flag to see if the item is still on a list. Reported-by: Ben Greear Tested-by: Hun-Kyi Wynn Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/wireless/scan.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 5ca8c7180141..503ebb86ba18 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -650,14 +650,14 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) bss = container_of(pub, struct cfg80211_internal_bss, pub); spin_lock_bh(&dev->bss_lock); + if (!list_empty(&bss->list)) { + list_del_init(&bss->list); + dev->bss_generation++; + rb_erase(&bss->rbn, &dev->bss_tree); - list_del(&bss->list); - dev->bss_generation++; - rb_erase(&bss->rbn, &dev->bss_tree); - + kref_put(&bss->ref, bss_release); + } spin_unlock_bh(&dev->bss_lock); - - kref_put(&bss->ref, bss_release); } EXPORT_SYMBOL(cfg80211_unlink_bss); -- cgit v1.2.3 From b4c656d2584875fc74bbda31687eeac9dbb03d41 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 30 Sep 2010 22:17:43 +0200 Subject: cfg80211: fix locking commit 2234362c427e2ef667595b9b81c0125003ac5607 upstream. Add missing unlocking of the wiphy in set_channel, and don't try to unlock a non-existing wiphy in set_cqm. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/wireless/nl80211.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index db71150b8040..da657d823114 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -758,11 +758,13 @@ static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info) result = get_rdev_dev_by_info_ifindex(info, &rdev, &netdev); if (result) - goto unlock; + goto unlock_rtnl; result = __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info); - unlock: + dev_put(netdev); + cfg80211_unlock_rdev(rdev); + unlock_rtnl: rtnl_unlock(); return result; @@ -4909,7 +4911,7 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); if (err) - goto unlock_rdev; + goto unlock_rtnl; wdev = dev->ieee80211_ptr; @@ -4926,9 +4928,10 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, err = rdev->ops->set_cqm_rssi_config(wdev->wiphy, dev, threshold, hysteresis); -unlock_rdev: + unlock_rdev: cfg80211_unlock_rdev(rdev); dev_put(dev); + unlock_rtnl: rtnl_unlock(); return err; -- cgit v1.2.3 From 12e3edfbbf42a116afc5e491930c5a1e56f4edb2 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 18 Oct 2010 17:44:51 -0700 Subject: cfg80211: fix regression on processing country IEs commit a171fba491f54216e356efa46096171a7ed01d10 upstream. The patch 4f366c5: wireless: only use alpha2 regulatory information from country IE removed some complex intersection we were always doing between the AP's country IE info and what we got from CRDA. When CRDA sent us back a regulatory domain we would do some sanity checks on that regulatory domain response we just got. Part of these sanity checks included checking that we already had performed an intersection for the request of NL80211_REGDOM_SET_BY_COUNTRY_IE type. This mean that cfg80211 was only processing country IEs for cases where we already had an intersection, but since we removed enforcing this this is no longer required, we should just apply the country IE country hint with the data received from CRDA. This patch has fixes intended for kernels >= 2.6.36. [AK: it seems to be needed for .35 too?? Kept for now] Reported-by: Easwar Krishnan Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/wireless/reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 8f0d97dd3109..55b11014b99c 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1695,7 +1695,7 @@ static int ignore_request(struct wiphy *wiphy, return 0; return -EALREADY; } - return REG_INTERSECT; + return 0; case NL80211_REGDOM_SET_BY_DRIVER: if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) { if (regdom_changes(pending_request->alpha2)) -- cgit v1.2.3 From ce838da05df6b16b9d2ac4cf4df1e86e6c9da16f Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 1 Oct 2010 17:05:19 -0400 Subject: mac80211: fix channel assumption for association done work commit e7480bbb926c5816e4fbfca70748096bbe0e4978 upstream. Be consistent and use the wk->chan instead of the local->hw.conf.channel for the association done work. This prevents any possible races against channel changes while we run this work. In the case that the race did happen we would be initializing the bit rates for the new AP under the assumption of a wrong channel and in the worst case, wrong band. This could lead to trying to assuming we could use CCK frames on 5 GHz, for example. This patch has a fix for kernels >= v2.6.34 Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/mac80211/mlme.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f803f8b72a93..578b2896387d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1210,7 +1210,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, rates = 0; basic_rates = 0; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + sband = local->hw.wiphy->bands[wk->chan->band]; for (i = 0; i < elems.supp_rates_len; i++) { int rate = (elems.supp_rates[i] & 0x7f) * 5; @@ -1246,11 +1246,11 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, } } - sta->sta.supp_rates[local->hw.conf.channel->band] = rates; + sta->sta.supp_rates[wk->chan->band] = rates; sdata->vif.bss_conf.basic_rates = basic_rates; /* cf. IEEE 802.11 9.2.12 */ - if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && + if (wk->chan->band == IEEE80211_BAND_2GHZ && have_higher_than_11mbit) sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; else -- cgit v1.2.3 From 96303095042fabda86dbadf7fea4ec3ad122a0f6 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 24 Sep 2010 21:59:57 -0400 Subject: mac80211: fix offchannel assumption upon association commit 8d4780eb1ece4e8109b4f6b2e5e61f7fc593c3f4 upstream. Association is dealt with as an atomic offchannel operation, we do this because we don't know we are associated until we get the associatin response from the AP. When we do get the associatin response though we were never clearing the offchannel state. This has a few implications, we told drivers we were still offchannel, and the first configured TX power for the channel does not take into account any power constraints. For ath9k this meant ANI calibration would not start upon association, and we'd have to wait until the first bgscan to be triggered. There may be other issues this resolves but I'm too lazy to comb the code to check. Cc: Amod Bodas Cc: Vasanth Thiagarajan Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/mac80211/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 52f15fe6f0ed..cd36d491df5c 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -106,7 +106,8 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) if (scan_chan) { chan = scan_chan; channel_type = NL80211_CHAN_NO_HT; - } else if (local->tmp_channel) { + } else if (local->tmp_channel && + local->oper_channel != local->tmp_channel) { chan = scan_chan = local->tmp_channel; channel_type = local->tmp_channel_type; } else { -- cgit v1.2.3 From b9676bfde50b87df6c2a214a46e7382ddd13a075 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Aug 2010 22:21:13 +0300 Subject: mac80211: Fix signal strength average initialization for CQM events commit 3ba06c6fbd651ed3377e584026d1c112b492cc8b upstream. The ave_beacon_signal value uses 1/16 dB unit and as such, must be initialized with the signal level of the first Beacon frame multiplied by 16. This fixes an issue where the initial CQM events are reported incorrectly with a burst of events while the running average approaches the correct value after the incorrect initialization. This could cause user space -based roaming decision process to get quite confused at the moment when we would like to go through authentication and DHCP. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/mac80211/mlme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 578b2896387d..6373bceb5365 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1488,7 +1488,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, ifmgd->last_beacon_signal = rx_status->signal; if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; - ifmgd->ave_beacon_signal = rx_status->signal; + ifmgd->ave_beacon_signal = rx_status->signal * 16; ifmgd->last_cqm_event_signal = 0; } else { ifmgd->ave_beacon_signal = -- cgit v1.2.3 From 82f7a2e95e8f41d56633822a649ff3621fc7a540 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 16 Sep 2010 15:12:29 -0400 Subject: mac80211: add helper for reseting the connection monitor commit be099e82e9cf6d5d65d044e9ef6fc8bee3c7a113 upstream. This will be used in another place later. The connection monitor was added as of 2.6.35 so these fixes will be applicable to >= 2.6.35. Cc: Paul Stewart Cc: Amod Bodas Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/mac80211/ieee80211_i.h | 1 + net/mac80211/mlme.c | 15 ++++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 1a9e2da37a93..f80461a2eb89 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1002,6 +1002,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, u64 timestamp); void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata); void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); +void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); /* IBSS code */ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 6373bceb5365..b88502af273d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -118,6 +118,15 @@ static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata) round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME)); } +void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata) +{ + if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) + return; + + mod_timer(&sdata->u.mgd.conn_mon_timer, + round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); +} + static int ecw2cw(int ecw) { return (1 << ecw) - 1; @@ -954,11 +963,7 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, if (is_multicast_ether_addr(hdr->addr1)) return; - if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) - return; - - mod_timer(&sdata->u.mgd.conn_mon_timer, - round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); + ieee80211_sta_reset_conn_monitor(sdata); } static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) -- cgit v1.2.3 From f4fa1333cd6577a63c532bc59586ac3b80f56c7e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 16 Sep 2010 15:12:31 -0400 Subject: mac80211: reset connection idle when going offchannel commit 4730d5977f3e12b828d354f7752cffd94bdf39e5 upstream. When we go offchannel mac80211 currently leaves alive the connection idle monitor. This should be instead postponed until we come back to our home channel, otherwise by the time we get back to the home channel we could be triggering unecesary probe requests. For APs that do not respond to unicast probe requests (Nexus One is a simple example) this means we essentially get disconnected after the probes fails. This patch has stable fixes for kernels [2.6.35+] Cc: Paul Stewart Cc: Amod Bodas Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/mac80211/offchannel.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index c36b1911987a..d4e837834209 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -22,12 +22,15 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; local->offchannel_ps_enabled = false; /* FIXME: what to do when local->pspolling is true? */ del_timer_sync(&local->dynamic_ps_timer); + del_timer_sync(&ifmgd->conn_mon_timer); + cancel_work_sync(&local->dynamic_ps_enable_work); if (local->hw.conf.flags & IEEE80211_CONF_PS) { @@ -85,6 +88,8 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) mod_timer(&local->dynamic_ps_timer, jiffies + msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); } + + ieee80211_sta_reset_conn_monitor(sdata); } void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) -- cgit v1.2.3 From 4311061afad44eff734ca645ee1e2833eb19c33d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 16 Sep 2010 15:12:32 -0400 Subject: mac80211: make the beacon monitor available externally commit d3a910a8e4e846b9a767d35483f4dc7c6de7af82 upstream. This will be used by other components next. The beacon monitor was added as of 2.6.34 so these fixes are applicable only to kernels >= 2.6.34. Cc: Paul Stewart Cc: Amod Bodas Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/mac80211/ieee80211_i.h | 1 + net/mac80211/mlme.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f80461a2eb89..a9f89472c9ce 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1003,6 +1003,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata); void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); +void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata); /* IBSS code */ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b88502af273d..387e8f5b9ff3 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -109,7 +109,7 @@ static void run_again(struct ieee80211_if_managed *ifmgd, mod_timer(&ifmgd->timer, timeout); } -static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata) +void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata) { if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER) return; @@ -1315,7 +1315,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, * Also start the timer that will detect beacon loss. */ ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); - mod_beacon_timer(sdata); + ieee80211_sta_reset_beacon_monitor(sdata); return true; } @@ -1418,7 +1418,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, * we have or will be receiving any beacons or data, so let's * schedule the timers again, just in case. */ - mod_beacon_timer(sdata); + ieee80211_sta_reset_beacon_monitor(sdata); mod_timer(&ifmgd->conn_mon_timer, round_jiffies_up(jiffies + @@ -1541,7 +1541,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, * Push the beacon loss detection into the future since * we are processing a beacon from the AP just now. */ - mod_beacon_timer(sdata); + ieee80211_sta_reset_beacon_monitor(sdata); ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, -- cgit v1.2.3 From 6f9867ece8be2ed323b085181d1ffa4424ab4ec6 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 16 Sep 2010 15:12:34 -0400 Subject: mac80211: send last 3/5 probe requests as unicast commit f01a067d9e4598c71e3c9ee3a84859d2e8af4f8e upstream. Some buggy APs do not respond to unicast probe requests or send unicast probe requests very delayed so in the worst case we should try to send broadcast probe requests, otherwise we can get disconnected from these APs. Even if drivers do not have filters to disregard probe responses from foreign APs mac80211 will only process probe responses from our associated AP for re-arming connection monitoring. We need to do this since the beacon monitor does not push back the connection monitor by design so even if we are getting beacons from these type of APs our connection monitor currently relies heavily on the way the probe requests are received on the AP. An example of an AP affected by this is the Nexus One, but this has also been observed with random APs. We can probably optimize this later by using null funcs instead of probe requests. For more details refer to: http://code.google.com/p/chromium-os/issues/detail?id=5715 This patch has fixes for stable kernels [2.6.35+]. Cc: Paul Stewart Cc: Amod Bodas Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/mac80211/mlme.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 387e8f5b9ff3..e722c5cbb2d9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -970,10 +970,19 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; const u8 *ssid; + u8 *dst = ifmgd->associated->bssid; + u8 unicast_limit = max(1, IEEE80211_MAX_PROBE_TRIES - 3); + + /* + * Try sending broadcast probe requests for the last three + * probe requests after the first ones failed since some + * buggy APs only support broadcast probe requests. + */ + if (ifmgd->probe_send_count >= unicast_limit) + dst = NULL; ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); - ieee80211_send_probe_req(sdata, ifmgd->associated->bssid, - ssid + 2, ssid[1], NULL, 0); + ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); ifmgd->probe_send_count++; ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; -- cgit v1.2.3 From b732c91f60cd067a497515b82af31950361367f4 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 16 Sep 2010 15:12:33 -0400 Subject: mac80211: disable beacon monitor while going offchannel commit 3bc3c0d748402e8c1f31b8569f5924d25d7b8e30 upstream. The beacon monitor should be disabled when going off channel to prevent spurious warnings and triggering connection deterioration work such as sending probe requests. Re-enable the beacon monitor once we come back to the home channel. This patch has fixes for stable kernels [2.6.34+]. Cc: Paul Stewart Cc: Amod Bodas Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/mac80211/offchannel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index d4e837834209..cf5ee305785b 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -29,6 +29,7 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) /* FIXME: what to do when local->pspolling is true? */ del_timer_sync(&local->dynamic_ps_timer); + del_timer_sync(&ifmgd->bcn_mon_timer); del_timer_sync(&ifmgd->conn_mon_timer); cancel_work_sync(&local->dynamic_ps_enable_work); @@ -89,6 +90,7 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); } + ieee80211_sta_reset_beacon_monitor(sdata); ieee80211_sta_reset_conn_monitor(sdata); } -- cgit v1.2.3 From 0fe79ffa47b60778e71fc8b2dcfc30eb9681db30 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 14 Sep 2010 22:06:53 +0200 Subject: mac80211: use correct station flags lock commit f5521b13880f4f4f612e1d20dd4f565122d16e04 upstream. This code is modifying the station flags, and as such should hold the flags lock so it can do so atomically vs. other flags modifications and readers. This issue was introduced when this code was added in eccb8e8f, as it used the wrong lock (thus not fixing the race that was previously documented in a comment.) Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/mac80211/cfg.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 67ee34f57df7..e8f3545ff8f4 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -639,6 +639,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, struct sta_info *sta, struct station_parameters *params) { + unsigned long flags; u32 rates; int i, j; struct ieee80211_supported_band *sband; @@ -647,7 +648,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, sband = local->hw.wiphy->bands[local->oper_channel->band]; - spin_lock_bh(&sta->lock); + spin_lock_irqsave(&sta->flaglock, flags); mask = params->sta_flags_mask; set = params->sta_flags_set; @@ -674,7 +675,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, if (set & BIT(NL80211_STA_FLAG_MFP)) sta->flags |= WLAN_STA_MFP; } - spin_unlock_bh(&sta->lock); + spin_unlock_irqrestore(&sta->flaglock, flags); /* * cfg80211 validates this (1-2007) and allows setting the AID -- cgit v1.2.3 From afa9194b3aee8846357236026905fb221c1d4564 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 21 Sep 2010 21:36:18 +0200 Subject: mac80211: clear txflags for ps-filtered frames commit eb7d3066cf864342e8ae6a5c1126a1602c4d06c0 upstream. This patch fixes stale mac80211_tx_control_flags for filtered / retried frames. Because ieee80211_handle_filtered_frame feeds skbs back into the tx path, they have to be stripped of some tx flags so they won't confuse the stack, driver or device. Acked-by: Johannes Berg Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/net/mac80211.h | 16 ++++++++++++++++ net/mac80211/status.c | 1 + 2 files changed, 17 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index de22cbfef232..323eca1110a9 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -287,6 +287,9 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_CTL_LDPC: tells the driver to use LDPC for this frame * @IEEE80211_TX_CTL_STBC: Enables Space-Time Block Coding (STBC) for this * frame and selects the maximum number of streams that it can use. + * + * Note: If you have to add new flags to the enumeration, then don't + * forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary. */ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), @@ -315,6 +318,19 @@ enum mac80211_tx_control_flags { #define IEEE80211_TX_CTL_STBC_SHIFT 23 }; +/* + * This definition is used as a mask to clear all temporary flags, which are + * set by the tx handlers for each transmission attempt by the mac80211 stack. + */ +#define IEEE80211_TX_TEMPORARY_FLAGS (IEEE80211_TX_CTL_NO_ACK | \ + IEEE80211_TX_CTL_CLEAR_PS_FILT | IEEE80211_TX_CTL_FIRST_FRAGMENT | \ + IEEE80211_TX_CTL_SEND_AFTER_DTIM | IEEE80211_TX_CTL_AMPDU | \ + IEEE80211_TX_STAT_TX_FILTERED | IEEE80211_TX_STAT_ACK | \ + IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_STAT_AMPDU_NO_BACK | \ + IEEE80211_TX_CTL_RATE_CTRL_PROBE | IEEE80211_TX_CTL_PSPOLL_RESPONSE | \ + IEEE80211_TX_CTL_MORE_FRAMES | IEEE80211_TX_CTL_LDPC | \ + IEEE80211_TX_CTL_STBC) + /** * enum mac80211_rate_control_flags - per-rate flags set by the * Rate Control algorithm. diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 94613af009f3..5f1310ad7535 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -58,6 +58,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, info->control.vif = &sta->sdata->vif; info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING | IEEE80211_TX_INTFL_RETRANSMISSION; + info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; sta->tx_filtered_count++; -- cgit v1.2.3 From 042a3f996b48464386e2b1ab6ecafc3be8a295c1 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 16 Sep 2010 15:12:30 -0400 Subject: mac80211: reset probe send counter upon connection timer reset commit 0c699c3a75d4e8d0d2c317f83048d8fd3ffe692a upstream. Upon beacon loss we send probe requests after 30 seconds of idle time and we wait for each probe response 1/2 second. We send a total of 3 probe requests before giving up on the AP. In the case that we reset the connection idle monitor we should reset the probe requests count to 0. Right now this won't help in any way but the next patch will. This patch has fixes for stable kernel [2.6.35+]. Cc: Paul Stewart Cc: Amod Bodas Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/mac80211/mlme.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e722c5cbb2d9..090b3e63ccf5 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -120,11 +120,15 @@ void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata) void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata) { + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) return; mod_timer(&sdata->u.mgd.conn_mon_timer, round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); + + ifmgd->probe_send_count = 0; } static int ecw2cw(int ecw) -- cgit v1.2.3 From 1416ef9a67f443b26bb9b9498ca14351616eedac Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 23 Oct 2010 10:59:57 +0530 Subject: mac80211: Fix ibss station got expired immediately commit c8716d9dc13c7f6ee92f2bfc6cc3b723b417bff8 upstream. Station addition in ieee80211_ibss_rx_queued_mgmt is not updating sta->last_rx which is causing station expiry in ieee80211_ibss_work path. So sta addition and deletion happens repeatedly. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/mac80211/ibss.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index b2cc1fda6cfd..c42987835f6c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -427,6 +427,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, if (!sta) return NULL; + sta->last_rx = jiffies; set_sta_flags(sta, WLAN_STA_AUTHORIZED); /* make sure mandatory rates are always added */ -- cgit v1.2.3 From a171652459e33373b16fe9d48e200aaa359010b8 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 16 Oct 2010 18:49:15 +0200 Subject: mac80211: don't sanitize invalid rates commit 5f4e6b2d3c74c1adda1cbfd9d9d30da22c7484fc upstream. I found this bug while poking around with a pure-gn AP. Commit: cfg80211/mac80211: Use more generic bitrate mask for rate control Added some sanity checks to ensure that each tx rate index is included in the configured mask and it would change any rate indexes if it wasn't. But, the current implementation doesn't take into account that the invalid rate index "-1" has a special meaning (= no further attempts) and it should not be "changed". Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/mac80211/rate.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 6d0bd198af19..68fc9c4e1537 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -326,6 +326,9 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, * if needed. */ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { + /* Skip invalid rates */ + if (info->control.rates[i].idx < 0) + break; /* Rate masking supports only legacy rates for now */ if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) continue; -- cgit v1.2.3 From a664846f7362bd6b9cf6f1e407dd86daa963da97 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Oct 2010 21:40:33 +0200 Subject: mac80211: delete AddBA response timer commit 44271488b91c9eecf249e075a1805dd887e222d2 upstream. We never delete the addBA response timer, which is typically fine, but if the station it belongs to is deleted very quickly after starting the BA session, before the peer had a chance to reply, the timer may fire after the station struct has been freed already. Therefore, we need to delete the timer in a suitable spot -- best when the session is being stopped (which will happen even then) in which case the delete will be a no-op most of the time. I've reproduced the scenario and tested the fix. This fixes the crash reported at http://mid.gmane.org/4CAB6F96.6090701@candelatech.com Reported-by: Ben Greear Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/mac80211/agg-tx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 98258b7341e3..f935490560ba 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -128,6 +128,7 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, enum ieee80211_back_parties initiator) { + struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; struct ieee80211_local *local = sta->local; int ret; u8 *state; @@ -137,6 +138,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, sta->sta.addr, tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ + del_timer_sync(&tid_tx->addba_resp_timer); + state = &sta->ampdu_mlme.tid_state_tx[tid]; if (*state == HT_AGG_STATE_OPERATIONAL) -- cgit v1.2.3 From 45edc39ac72b39b936b2c99361783d4fb8bc44c1 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Thu, 30 Sep 2010 13:34:40 +0000 Subject: isdn/gigaset: fix bas_gigaset AT read error handling commit c8701a08d6a4efeae45d84d0aa87172f23b14e3c upstream. Rework the handling of USB errors in AT response reads to fix a possible infinite retry loop and a memory leak, and silence a few overly verbose kernel messages. Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/isdn/gigaset/bas-gigaset.c | 83 +++++++++++++++----------------------- 1 file changed, 33 insertions(+), 50 deletions(-) diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 47a5ffec55a3..b25f01e893db 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -438,23 +438,27 @@ static void cmd_in_timeout(unsigned long data) return; } - if (ucs->retry_cmd_in++ < BAS_RETRY) { - dev_notice(cs->dev, "control read: timeout, retry %d\n", - ucs->retry_cmd_in); - rc = atread_submit(cs, BAS_TIMEOUT); - if (rc >= 0 || rc == -ENODEV) - /* resubmitted or disconnected */ - /* - bypass regular exit block */ - return; - } else { + if (ucs->retry_cmd_in++ >= BAS_RETRY) { dev_err(cs->dev, "control read: timeout, giving up after %d tries\n", ucs->retry_cmd_in); + kfree(ucs->rcvbuf); + ucs->rcvbuf = NULL; + ucs->rcvbuf_size = 0; + error_reset(cs); + return; + } + + gig_dbg(DEBUG_USBREQ, "%s: timeout, retry %d", + __func__, ucs->retry_cmd_in); + rc = atread_submit(cs, BAS_TIMEOUT); + if (rc < 0) { + kfree(ucs->rcvbuf); + ucs->rcvbuf = NULL; + ucs->rcvbuf_size = 0; + if (rc != -ENODEV) + error_reset(cs); } - kfree(ucs->rcvbuf); - ucs->rcvbuf = NULL; - ucs->rcvbuf_size = 0; - error_reset(cs); } /* read_ctrl_callback @@ -470,18 +474,11 @@ static void read_ctrl_callback(struct urb *urb) struct cardstate *cs = inbuf->cs; struct bas_cardstate *ucs = cs->hw.bas; int status = urb->status; - int have_data = 0; unsigned numbytes; int rc; update_basstate(ucs, 0, BS_ATRDPEND); wake_up(&ucs->waitqueue); - - if (!ucs->rcvbuf_size) { - dev_warn(cs->dev, "%s: no receive in progress\n", __func__); - return; - } - del_timer(&ucs->timer_cmd_in); switch (status) { @@ -495,19 +492,10 @@ static void read_ctrl_callback(struct urb *urb) numbytes = ucs->rcvbuf_size; } - /* copy received bytes to inbuf */ - have_data = gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes); - - if (unlikely(numbytes < ucs->rcvbuf_size)) { - /* incomplete - resubmit for remaining bytes */ - ucs->rcvbuf_size -= numbytes; - ucs->retry_cmd_in = 0; - rc = atread_submit(cs, BAS_TIMEOUT); - if (rc >= 0 || rc == -ENODEV) - /* resubmitted or disconnected */ - /* - bypass regular exit block */ - return; - error_reset(cs); + /* copy received bytes to inbuf, notify event layer */ + if (gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes)) { + gig_dbg(DEBUG_INTR, "%s-->BH", __func__); + gigaset_schedule_event(cs); } break; @@ -516,37 +504,32 @@ static void read_ctrl_callback(struct urb *urb) case -EINPROGRESS: /* pending */ case -ENODEV: /* device removed */ case -ESHUTDOWN: /* device shut down */ - /* no action necessary */ + /* no further action necessary */ gig_dbg(DEBUG_USBREQ, "%s: %s", __func__, get_usb_statmsg(status)); break; - default: /* severe trouble */ - dev_warn(cs->dev, "control read: %s\n", - get_usb_statmsg(status)); + default: /* other errors: retry */ if (ucs->retry_cmd_in++ < BAS_RETRY) { - dev_notice(cs->dev, "control read: retry %d\n", - ucs->retry_cmd_in); + gig_dbg(DEBUG_USBREQ, "%s: %s, retry %d", __func__, + get_usb_statmsg(status), ucs->retry_cmd_in); rc = atread_submit(cs, BAS_TIMEOUT); - if (rc >= 0 || rc == -ENODEV) - /* resubmitted or disconnected */ - /* - bypass regular exit block */ + if (rc >= 0) + /* successfully resubmitted, skip freeing */ return; - } else { - dev_err(cs->dev, - "control read: giving up after %d tries\n", - ucs->retry_cmd_in); + if (rc == -ENODEV) + /* disconnect, no further action necessary */ + break; } + dev_err(cs->dev, "control read: %s, giving up after %d tries\n", + get_usb_statmsg(status), ucs->retry_cmd_in); error_reset(cs); } + /* read finished, free buffer */ kfree(ucs->rcvbuf); ucs->rcvbuf = NULL; ucs->rcvbuf_size = 0; - if (have_data) { - gig_dbg(DEBUG_INTR, "%s-->BH", __func__); - gigaset_schedule_event(cs); - } } /* atread_submit -- cgit v1.2.3 From f1c7c6e08fa6411977fb30bc9c2c6d532e3e1b0e Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Thu, 30 Sep 2010 13:34:51 +0000 Subject: isdn/gigaset: correct bas_gigaset rx buffer handling commit f3d531b99fb30945b4a64d6e2e86e1e62605aca5 upstream. In transparent data reception, avoid a NULL pointer dereference in case an skbuff cannot be allocated, remove an inappropriate call to the HDLC flush routine, and correct the accounting of received bytes for continued buffers. Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/isdn/gigaset/isocdata.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 2dfd346fc889..f39ccdf87a17 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -842,13 +842,14 @@ static inline void trans_receive(unsigned char *src, unsigned count, if (unlikely(bcs->ignore)) { bcs->ignore--; - hdlc_flush(bcs); return; } skb = bcs->rx_skb; - if (skb == NULL) + if (skb == NULL) { skb = gigaset_new_rx_skb(bcs); - bcs->hw.bas->goodbytes += skb->len; + if (skb == NULL) + return; + } dobytes = bcs->rx_bufsize - skb->len; while (count > 0) { dst = skb_put(skb, count < dobytes ? count : dobytes); @@ -860,6 +861,7 @@ static inline void trans_receive(unsigned char *src, unsigned count, if (dobytes == 0) { dump_bytes(DEBUG_STREAM_DUMP, "rcv data", skb->data, skb->len); + bcs->hw.bas->goodbytes += skb->len; gigaset_skb_rcvd(bcs, skb); skb = gigaset_new_rx_skb(bcs); if (skb == NULL) -- cgit v1.2.3 From 6d4df88a9baaeae077038956f9cf876de3e3ca16 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Thu, 30 Sep 2010 13:34:30 +0000 Subject: isdn/gigaset: bas_gigaset locking fix commit b33ffa5cbf52ee751bb8068218ebb3c742c5a515 upstream. Unlock cs->lock before calling error_hangup() which is marked "cs->lock must not be held". Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/isdn/gigaset/bas-gigaset.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index b25f01e893db..fef5e7559434 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -1599,13 +1599,13 @@ static int gigaset_init_bchannel(struct bc_state *bcs) ret = starturbs(bcs); if (ret < 0) { + spin_unlock_irqrestore(&cs->lock, flags); dev_err(cs->dev, "could not start isochronous I/O for channel B%d: %s\n", bcs->channel + 1, ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret)); if (ret != -ENODEV) error_hangup(bcs); - spin_unlock_irqrestore(&cs->lock, flags); return ret; } @@ -1615,11 +1615,11 @@ static int gigaset_init_bchannel(struct bc_state *bcs) dev_err(cs->dev, "could not open channel B%d\n", bcs->channel + 1); stopurbs(bcs->hw.bas); - if (ret != -ENODEV) - error_hangup(bcs); } spin_unlock_irqrestore(&cs->lock, flags); + if (ret < 0 && ret != -ENODEV) + error_hangup(bcs); return ret; } -- cgit v1.2.3 From 93782b496da0239a3decc2d9860a6147598d703e Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Sun, 24 Oct 2010 18:16:57 +0200 Subject: i2c-pca-platform: Change device name of request_irq commit 323584436db0cb05286425d4dfd9516fce88487f upstream. i2c->adap.name shouldn't be used in request_irq. Instead the driver name "i2c-pca-platform" should be used. Signed-off-by: Nobuhiro Iwamatsu Acked-by: Wolfram Sang Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/i2c/busses/i2c-pca-platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index 5f6d7f89e225..ace67995d7de 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -224,7 +224,7 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev) if (irq) { ret = request_irq(irq, i2c_pca_pf_handler, - IRQF_TRIGGER_FALLING, i2c->adap.name, i2c); + IRQF_TRIGGER_FALLING, pdev->name, i2c); if (ret) goto e_reqirq; } -- cgit v1.2.3 From a7d67728b4fc6d51d3f3127bc0490cdb5688e2ab Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Fri, 17 Sep 2010 01:16:25 +0000 Subject: viafb: fix i2c_transfer error handling commit 85c5702ac046b14713f776d59768252d8ed8018f upstream. i2c_transfer returns negative errno on error and number of messages processed on success. Just returning this value would give a poor interface as it is not obvious that you must compare with 2 after reading 1 or n bytes and with 1 after writing 1 byte to determine if it was successful. To avoid this error prone interface convert the error code of a successful read/write to zero and all other non-negative values to an negative error code. This fixes a regression introduced by via: Rationalize vt1636 detection which resulted in no longer detecting a VT1636 chip and therefore has broken the output in configurations which contain this chip. Signed-off-by: Florian Tobias Schandinat Acked-by: Jonathan Corbet Cc: Joseph Chan Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/video/via/via_i2c.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c index da9e4ca94b17..021112e279de 100644 --- a/drivers/video/via/via_i2c.c +++ b/drivers/video/via/via_i2c.c @@ -114,6 +114,7 @@ static void via_i2c_setsda(void *data, int state) int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata) { + int ret; u8 mm1[] = {0x00}; struct i2c_msg msgs[2]; @@ -126,11 +127,18 @@ int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata) mm1[0] = index; msgs[0].len = 1; msgs[1].len = 1; msgs[0].buf = mm1; msgs[1].buf = pdata; - return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2); + ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2); + if (ret == 2) + ret = 0; + else if (ret >= 0) + ret = -EIO; + + return ret; } int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data) { + int ret; u8 msg[2] = { index, data }; struct i2c_msg msgs; @@ -140,11 +148,18 @@ int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data) msgs.addr = slave_addr / 2; msgs.len = 2; msgs.buf = msg; - return i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1); + ret = i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1); + if (ret == 1) + ret = 0; + else if (ret >= 0) + ret = -EIO; + + return ret; } int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len) { + int ret; u8 mm1[] = {0x00}; struct i2c_msg msgs[2]; @@ -156,7 +171,13 @@ int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len mm1[0] = index; msgs[0].len = 1; msgs[1].len = buff_len; msgs[0].buf = mm1; msgs[1].buf = buff; - return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2); + ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2); + if (ret == 2) + ret = 0; + else if (ret >= 0) + ret = -EIO; + + return ret; } /* -- cgit v1.2.3 From af4cd8591cc750feb6f95f583a9bb79e349454d9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 17 Nov 2010 17:56:49 -0500 Subject: drm/radeon/kms: register an i2c adapter name for the dp aux bus commit a5193fe50e7f21c26d22c17c8196420fac1a3ca7 upstream. This causes the connector to not be added since i2c init fails for the adapter. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=31688 Noticed by Ari Savolainen. Signed-off-by: Alex Deucher Cc: Ari Savolainen Cc: Jean Delvare Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/radeon_i2c.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 0cd2704e9a48..5c25846481f4 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -942,6 +942,7 @@ struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, i2c->rec = *rec; i2c->adapter.owner = THIS_MODULE; i2c->dev = dev; + sprintf(i2c->adapter.name, "Radeon aux bus %s", name); i2c_set_adapdata(&i2c->adapter, i2c); i2c->adapter.algo_data = &i2c->algo.dp; i2c->algo.dp.aux_ch = radeon_dp_i2c_aux_ch; -- cgit v1.2.3 From fef4663d0ebc4456007953d31870ebc55d7b60af Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 21 Oct 2010 08:55:13 +0200 Subject: ALSA: hda - Fix wrong SPDIF NID assignment for CA0110 commit 24b55c69b66eb2a122842820ec14ab215fc8572f upstream. The dig_out_nid field must take a digital-converter widget, but the current ca0110 parser passed the pin wrongly instead. Reported-by: Wai Yew CHAY Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_ca0110.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c index af478019088e..9544463cf862 100644 --- a/sound/pci/hda/patch_ca0110.c +++ b/sound/pci/hda/patch_ca0110.c @@ -489,7 +489,7 @@ static void parse_digital(struct hda_codec *codec) if (cfg->dig_outs && snd_hda_get_connections(codec, cfg->dig_out_pins[0], &spec->dig_out, 1) == 1) - spec->multiout.dig_out_nid = cfg->dig_out_pins[0]; + spec->multiout.dig_out_nid = spec->dig_out; } static int ca0110_parse_auto_config(struct hda_codec *codec) -- cgit v1.2.3 From 7810c3d74b3b5c06f828853424b20380526064ea Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 21 Oct 2010 09:03:25 +0200 Subject: ALSA: hda - Add some workarounds for Creative IBG commit 14d34f166c57e77e3d7f9bc8b43d349186d922c1 upstream. Creative HD-audio controller chips require some workarounds: - Additional delay before RIRB response - Set the initial RIRB counter to 0xc0 The latter seems to be done in general in Windows driver, so we may use this value later for all types if it's confirmed to work better. Reported-by: Wai Yew CHAY Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/hda_intel.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 1df25cf5ce38..d83cc563e468 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -457,6 +457,7 @@ enum { AZX_DRIVER_ULI, AZX_DRIVER_NVIDIA, AZX_DRIVER_TERA, + AZX_DRIVER_CTX, AZX_DRIVER_GENERIC, AZX_NUM_DRIVERS, /* keep this as last entry */ }; @@ -472,6 +473,7 @@ static char *driver_short_names[] __devinitdata = { [AZX_DRIVER_ULI] = "HDA ULI M5461", [AZX_DRIVER_NVIDIA] = "HDA NVidia", [AZX_DRIVER_TERA] = "HDA Teradici", + [AZX_DRIVER_CTX] = "HDA Creative", [AZX_DRIVER_GENERIC] = "HD-Audio Generic", }; @@ -562,7 +564,10 @@ static void azx_init_cmd_io(struct azx *chip) /* reset the rirb hw write pointer */ azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST); /* set N=1, get RIRB response interrupt for new entry */ - azx_writew(chip, RINTCNT, 1); + if (chip->driver_type == AZX_DRIVER_CTX) + azx_writew(chip, RINTCNT, 0xc0); + else + azx_writew(chip, RINTCNT, 1); /* enable rirb dma and response irq */ azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); spin_unlock_irq(&chip->reg_lock); @@ -1135,8 +1140,11 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) /* clear rirb int */ status = azx_readb(chip, RIRBSTS); if (status & RIRB_INT_MASK) { - if (status & RIRB_INT_RESPONSE) + if (status & RIRB_INT_RESPONSE) { + if (chip->driver_type == AZX_DRIVER_CTX) + udelay(80); azx_update_rirb(chip); + } azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); } @@ -2790,10 +2798,10 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID), .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, .class_mask = 0xffffff, - .driver_data = AZX_DRIVER_GENERIC }, + .driver_data = AZX_DRIVER_CTX }, #else /* this entry seems still valid -- i.e. without emu20kx chip */ - { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_GENERIC }, + { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_CTX }, #endif /* AMD/ATI Generic, PCI class code and Vendor ID for HD Audio */ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID), -- cgit v1.2.3 From 4f313ac597120c8b657dba169b3bb8b71573b9de Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 8 Oct 2010 10:48:50 +0200 Subject: ALSA: OSS mixer emulation - fix locking commit 838c364ff05c143fd1810e8ad1469935d6c23a7a upstream. Fix mutex release and cleanup some locking code. Signed-off-by: Jaroslav Kysela Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/core/oss/mixer_oss.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index f50ebf20df96..8442a088677d 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -618,8 +618,10 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer, if (numid == ID_UNKNOWN) return; down_read(&card->controls_rwsem); - if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) + if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { + up_read(&card->controls_rwsem); return; + } uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) @@ -658,7 +660,7 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer, return; down_read(&card->controls_rwsem); if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { - up_read(&fmixer->card->controls_rwsem); + up_read(&card->controls_rwsem); return; } uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); @@ -797,7 +799,7 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) { err = -ENOMEM; - goto __unlock; + goto __free_only; } down_read(&card->controls_rwsem); kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0); @@ -826,6 +828,7 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned err = 0; __unlock: up_read(&card->controls_rwsem); + __free_only: kfree(uctl); kfree(uinfo); return err; @@ -847,7 +850,7 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) { err = -ENOMEM; - goto __unlock; + goto __free_only; } down_read(&card->controls_rwsem); kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0); @@ -880,6 +883,7 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned err = 0; __unlock: up_read(&card->controls_rwsem); + __free_only: kfree(uctl); kfree(uinfo); return err; -- cgit v1.2.3 From 4d610bd1b4eccec1002bddd584f47d1bfe612e2d Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Mon, 25 Oct 2010 23:52:04 +0200 Subject: ALSA: HDA: Enable internal mic on Dell E6410 and Dell E6510 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Not upstream as .37 fixes this differently in a much more complete way that is not able to be backported easily.] (Ported on top of 2.6.36) BugLink: http://launchpad.net/bugs/628961 BugLink: http://launchpad.net/bugs/605047 Signed-off-by: David Henningsson Signed-off-by: Diego Elio Pettenò Acked-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_sigmatel.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index b8d730c47df1..0d69d8edcd8b 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -93,6 +93,7 @@ enum { STAC_92HD83XXX_REF, STAC_92HD83XXX_PWR_REF, STAC_DELL_S14, + STAC_DELL_E6410, STAC_92HD83XXX_HP, STAC_92HD83XXX_MODELS }; @@ -1192,6 +1193,13 @@ static int stac92xx_build_controls(struct hda_codec *codec) return 0; } +/* Deliberately turn off 0x0f (Dock Mic) to make it choose Int Mic instead */ +static unsigned int dell_e6410_pin_configs[10] = { + 0x04a11020, 0x0421101f, 0x400000f0, 0x90170110, + 0x23011050, 0x40f000f0, 0x400000f0, 0x90a60130, + 0x40f000f0, 0x40f000f0, +}; + static unsigned int ref9200_pin_configs[8] = { 0x01c47010, 0x01447010, 0x0221401f, 0x01114010, 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, @@ -1636,6 +1644,7 @@ static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, [STAC_DELL_S14] = dell_s14_pin_configs, + [STAC_DELL_E6410] = dell_e6410_pin_configs, }; static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { @@ -1643,6 +1652,7 @@ static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { [STAC_92HD83XXX_REF] = "ref", [STAC_92HD83XXX_PWR_REF] = "mic-ref", [STAC_DELL_S14] = "dell-s14", + [STAC_DELL_E6410] = "dell-e6410", [STAC_92HD83XXX_HP] = "hp", }; @@ -1654,6 +1664,10 @@ static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { "DFI LanParty", STAC_92HD83XXX_REF), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, "unknown Dell", STAC_DELL_S14), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x040a, + "Dell E6410", STAC_DELL_E6410), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x040b, + "Dell E6510", STAC_DELL_E6410), SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600, "HP", STAC_92HD83XXX_HP), {} /* terminator */ -- cgit v1.2.3 From ae813a8a26a9f2df98e66471766f04522c7bbe8c Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Wed, 17 Nov 2010 16:32:59 +0000 Subject: powerpc: Fix call to subpage_protection() commit 1c2c25c78740b2796c7c06640784cb6732fa4907 upstream. In: powerpc/mm: Fix pgtable cache cleanup with CONFIG_PPC_SUBPAGE_PROT commit d28513bc7f675d28b479db666d572e078ecf182d Author: David Gibson subpage_protection() was changed to to take an mm rather a pgdir but it didn't change calling site in hashpage_preload(). The change wasn't noticed at compile time since hashpage_preload() used a void* as the parameter to subpage_protection(). This is obviously wrong and can trigger the following crash when CONFIG_SLAB, CONFIG_DEBUG_SLAB, CONFIG_PPC_64K_PAGES CONFIG_PPC_SUBPAGE_PROT are enabled. Freeing unused kernel memory: 704k freed Unable to handle kernel paging request for data at address 0x6b6b6b6b6b6c49b7 Faulting instruction address: 0xc0000000000410f4 cpu 0x2: Vector: 300 (Data Access) at [c00000004233f590] pc: c0000000000410f4: .hash_preload+0x258/0x338 lr: c000000000041054: .hash_preload+0x1b8/0x338 sp: c00000004233f810 msr: 8000000000009032 dar: 6b6b6b6b6b6c49b7 dsisr: 40000000 current = 0xc00000007e2c0070 paca = 0xc000000007fe0500 pid = 1, comm = init enter ? for help [c00000004233f810] c000000000041020 .hash_preload+0x184/0x338 (unreliable) [c00000004233f8f0] c00000000003ed98 .update_mmu_cache+0xb0/0xd0 [c00000004233f990] c000000000157754 .__do_fault+0x48c/0x5dc [c00000004233faa0] c000000000158fd0 .handle_mm_fault+0x508/0xa8c [c00000004233fb90] c0000000006acdd4 .do_page_fault+0x428/0x6ac [c00000004233fe30] c000000000005260 handle_page_fault+0x20/0x74 Reported-by: Jim Keniston Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Michael Neuling Signed-off-by: Andi Kleen cc: David Gibson Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/mm/hash_utils_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 09dffe6efa46..1eb64ba43a08 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -1122,7 +1122,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, else #endif /* CONFIG_PPC_HAS_HASH_64K */ rc = __hash_page_4K(ea, access, vsid, ptep, trap, local, ssize, - subpage_protection(pgdir, ea)); + subpage_protection(mm, ea)); /* Dump some info in case of hash insertion failure, they should * never happen so it is really useful to know if/when they do -- cgit v1.2.3 From efbc3702f85371a9bb53e68c72d3738bf678fd5c Mon Sep 17 00:00:00 2001 From: Thomas Backlund Date: Thu, 21 Oct 2010 13:19:10 +0300 Subject: microblaze: Fix build with make 3.82 commit b843e4ec01991a386a9e0e9030703524446e03da upstream. When running make headers_install_all on x86_64 and make 3.82 I hit this: arch/microblaze/Makefile:80: *** mixed implicit and normal rules. Stop. make: *** [headers_install_all] Error 2 So split the rules to satisfy make 3.82. Signed-off-by: Thomas Backlund Signed-off-by: Michal Simek Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/microblaze/Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile index 72f6e8583746..45e6afce51ed 100644 --- a/arch/microblaze/Makefile +++ b/arch/microblaze/Makefile @@ -72,12 +72,16 @@ export MMU DTB all: linux.bin -BOOT_TARGETS = linux.bin linux.bin.gz simpleImage.% +# With make 3.82 we cannot mix normal and wildcard targets +BOOT_TARGETS1 = linux.bin linux.bin.gz +BOOT_TARGETS2 = simpleImage.% archclean: $(Q)$(MAKE) $(clean)=$(boot) -$(BOOT_TARGETS): vmlinux +$(BOOT_TARGETS1): vmlinux + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ +$(BOOT_TARGETS2): vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ define archhelp -- cgit v1.2.3 From c41948fcb78d07feb70c6860976d8ddfd82a6423 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 4 Oct 2010 17:59:08 -0400 Subject: NFSv4: Don't call nfs4_reclaim_complete() on receiving NFS4ERR_STALE_CLIENTID commit 6eaa61496fb3b93cceface7a296415fc4c030bce upstream. If the server sends us an NFS4ERR_STALE_CLIENTID while the state management thread is busy reclaiming state, we do want to treat all state that wasn't reclaimed before the STALE_CLIENTID as if a network partition occurred (see the edge conditions described in RFC3530 and RFC5661). What we do not want to do is to send an nfs4_reclaim_complete(), since we haven't yet even started reclaiming state after the server rebooted. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfs/nfs4state.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 34acf5926fdc..53f05ddce765 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1111,17 +1111,14 @@ static void nfs4_reclaim_complete(struct nfs_client *clp, (void)ops->reclaim_complete(clp); } -static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) +static int nfs4_state_clear_reclaim_reboot(struct nfs_client *clp) { struct nfs4_state_owner *sp; struct rb_node *pos; struct nfs4_state *state; if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) - return; - - nfs4_reclaim_complete(clp, - nfs4_reboot_recovery_ops[clp->cl_minorversion]); + return 0; for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) { sp = rb_entry(pos, struct nfs4_state_owner, so_client_node); @@ -1135,6 +1132,14 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) } nfs_delegation_reap_unclaimed(clp); + return 1; +} + +static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) +{ + if (!nfs4_state_clear_reclaim_reboot(clp)) + return; + nfs4_reclaim_complete(clp, nfs4_reboot_recovery_ops[clp->cl_minorversion]); } static void nfs_delegation_clear_all(struct nfs_client *clp) @@ -1161,7 +1166,7 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_LEASE_MOVED: set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); - nfs4_state_end_reclaim_reboot(clp); + nfs4_state_clear_reclaim_reboot(clp); nfs4_state_start_reclaim_reboot(clp); break; case -NFS4ERR_EXPIRED: -- cgit v1.2.3 From 7340643fd14c71ff34067c920a1a5027d5fc21a6 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 4 Oct 2010 17:59:08 -0400 Subject: NFSv4: Don't call nfs4_state_mark_reclaim_reboot() from error handlers commit ae1007d37e00144b72906a4bdc47d517ae91bcc1 upstream. In the case of a server reboot, the state recovery thread starts by calling nfs4_state_end_reclaim_reboot() in order to avoid edge conditions when the server reboots while the client is in the middle of recovery. However, if the client has already marked the nfs4_state as requiring reboot recovery, then the above behaviour will cause the recovery thread to treat the open as if it was part of such an edge condition: the open will be recovered as if it was part of a lease expiration (and all the locks will be lost). Fix is to remove the call to nfs4_state_mark_reclaim_reboot from nfs4_async_handle_error(), and nfs4_handle_exception(). Instead we leave it to the recovery thread to do this for us. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfs/nfs4proc.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 330a3c9a1a03..d2ced8bcde95 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -255,9 +255,6 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, nfs4_state_mark_reclaim_nograce(clp, state); goto do_state_recovery; case -NFS4ERR_STALE_STATEID: - if (state == NULL) - break; - nfs4_state_mark_reclaim_reboot(clp, state); case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_EXPIRED: goto do_state_recovery; @@ -3479,9 +3476,6 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, nfs4_state_mark_reclaim_nograce(clp, state); goto do_state_recovery; case -NFS4ERR_STALE_STATEID: - if (state == NULL) - break; - nfs4_state_mark_reclaim_reboot(clp, state); case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_EXPIRED: goto do_state_recovery; -- cgit v1.2.3 From 7c1f052075fa542153689ebbebcd6a6f959cde4b Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 4 Oct 2010 17:59:08 -0400 Subject: NFSv4: Fix open recovery commit b0ed9dbc24f1fd912b2dd08b995153cafc1d5b1c upstream. NFSv4 open recovery is currently broken: since we do not clear the state->flags states before attempting recovery, we end up with the 'can_open_cached()' function triggering. This again leads to no OPEN call being put on the wire. Reported-by: Sachin Prabhu Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfs/nfs4proc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index d2ced8bcde95..f7b7698cd9a7 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1099,6 +1099,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * clear_bit(NFS_DELEGATED_STATE, &state->flags); smp_rmb(); if (state->n_rdwr != 0) { + clear_bit(NFS_O_RDWR_STATE, &state->flags); ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate); if (ret != 0) return ret; @@ -1106,6 +1107,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * return -ESTALE; } if (state->n_wronly != 0) { + clear_bit(NFS_O_WRONLY_STATE, &state->flags); ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate); if (ret != 0) return ret; @@ -1113,6 +1115,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * return -ESTALE; } if (state->n_rdonly != 0) { + clear_bit(NFS_O_RDONLY_STATE, &state->flags); ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate); if (ret != 0) return ret; -- cgit v1.2.3 From babbccf4d973c20eb79b5879a669106bd67b2f33 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 4 Oct 2010 17:59:08 -0400 Subject: NFS: Don't SIGBUS if nfs_vm_page_mkwrite races with a cache invalidation commit bc4866b6e0b44f8ea0df22a16e5927714beb4983 upstream. In the case where we lock the page, and then find out that the page has been thrown out of the page cache, we should just return VM_FAULT_NOPAGE. This is what block_page_mkwrite() does in these situations. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfs/file.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index f036153d9f50..e8929eeb9e5a 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -560,7 +560,7 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) struct file *filp = vma->vm_file; struct dentry *dentry = filp->f_path.dentry; unsigned pagelen; - int ret = -EINVAL; + int ret = VM_FAULT_NOPAGE; struct address_space *mapping; dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n", @@ -576,21 +576,20 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) if (mapping != dentry->d_inode->i_mapping) goto out_unlock; - ret = 0; pagelen = nfs_page_length(page); if (pagelen == 0) goto out_unlock; - ret = nfs_flush_incompatible(filp, page); - if (ret != 0) - goto out_unlock; + ret = VM_FAULT_LOCKED; + if (nfs_flush_incompatible(filp, page) == 0 && + nfs_updatepage(filp, page, 0, pagelen) == 0) + goto out; - ret = nfs_updatepage(filp, page, 0, pagelen); + ret = VM_FAULT_SIGBUS; out_unlock: - if (!ret) - return VM_FAULT_LOCKED; unlock_page(page); - return VM_FAULT_SIGBUS; +out: + return ret; } static const struct vm_operations_struct nfs_file_vm_ops = { -- cgit v1.2.3 From cde76274952b114223f4b36123ffa3450c5bbf8a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 25 Oct 2010 19:44:00 -0400 Subject: drm/radeon/kms: MC vram map needs to be >= pci aperture size commit b7d8cce5b558e0c0aa6898c9865356481598b46d upstream. The vram map in the radeon memory controller needs to be >= the pci aperture size. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=28402 The problematic cards in the above bug have 64 MB of vram, but the pci aperture is 128 MB and the MC vram map was only 64 MB. This can lead to hangs. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/r100.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index a89a15ab524d..5c37c4884cf3 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -2321,6 +2321,9 @@ void r100_vram_init_sizes(struct radeon_device *rdev) /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - * Novell bug 204882 + along with lots of ubuntu ones */ + if (rdev->mc.aper_size > config_aper_size) + config_aper_size = rdev->mc.aper_size; + if (config_aper_size > rdev->mc.real_vram_size) rdev->mc.mc_vram_size = config_aper_size; else -- cgit v1.2.3 From b8e9a4a45f8427837f4dba89bda4d4e3f3a5c726 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 18 Oct 2010 23:54:56 -0400 Subject: drm/radeon/kms: properly compute group_size on 6xx/7xx commit 881fe6c1d06bf49f4ab7aef212cdaf66bd059614 upstream. Needed for tiled surfaces. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/r600.c | 7 +++++-- drivers/gpu/drm/radeon/rv770.c | 9 +++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index eddeff34e73a..a40be952554a 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1592,8 +1592,11 @@ void r600_gpu_init(struct radeon_device *rdev) rdev->config.r600.tiling_npipes = rdev->config.r600.max_tile_pipes; rdev->config.r600.tiling_nbanks = 4 << ((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); tiling_config |= BANK_TILING((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); - tiling_config |= GROUP_SIZE(0); - rdev->config.r600.tiling_group_size = 256; + tiling_config |= GROUP_SIZE((ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); + if ((ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) + rdev->config.r600.tiling_group_size = 512; + else + rdev->config.r600.tiling_group_size = 256; tmp = (ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT; if (tmp > 3) { tiling_config |= ROW_TILING(3); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 67e807371a08..082c38044154 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -627,10 +627,11 @@ static void rv770_gpu_init(struct radeon_device *rdev) else gb_tiling_config |= BANK_TILING((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); rdev->config.rv770.tiling_nbanks = 4 << ((gb_tiling_config >> 4) & 0x3); - - gb_tiling_config |= GROUP_SIZE(0); - rdev->config.rv770.tiling_group_size = 256; - + gb_tiling_config |= GROUP_SIZE((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); + if ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) + rdev->config.rv770.tiling_group_size = 512; + else + rdev->config.rv770.tiling_group_size = 256; if (((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT) > 3) { gb_tiling_config |= ROW_TILING(3); gb_tiling_config |= SAMPLE_SPLIT(3); -- cgit v1.2.3 From 1fbb45731dfca95002b1b24679648fecdbab42d3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 6 Oct 2010 00:13:04 -0400 Subject: drm/radeon/kms: make sure blit addr masks are 64 bit commit 2126d0a4a205e2d6b763434f892524cd60f74228 upstream. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/r600_blit_kms.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index d13622ae74e9..863e2bfe5060 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c @@ -623,8 +623,8 @@ void r600_kms_blit_copy(struct radeon_device *rdev, int src_x = src_gpu_addr & 255; int dst_x = dst_gpu_addr & 255; int h = 1; - src_gpu_addr = src_gpu_addr & ~255; - dst_gpu_addr = dst_gpu_addr & ~255; + src_gpu_addr = src_gpu_addr & ~255ULL; + dst_gpu_addr = dst_gpu_addr & ~255ULL; if (!src_x && !dst_x) { h = (cur_size / max_bytes); @@ -717,8 +717,8 @@ void r600_kms_blit_copy(struct radeon_device *rdev, int src_x = (src_gpu_addr & 255); int dst_x = (dst_gpu_addr & 255); int h = 1; - src_gpu_addr = src_gpu_addr & ~255; - dst_gpu_addr = dst_gpu_addr & ~255; + src_gpu_addr = src_gpu_addr & ~255ULL; + dst_gpu_addr = dst_gpu_addr & ~255ULL; if (!src_x && !dst_x) { h = (cur_size / max_bytes); -- cgit v1.2.3 From 6a132e669ac1845bef63801129800765c97d06d4 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 27 Oct 2010 01:02:35 -0400 Subject: drm/radeon/kms: fix handling of tex lookup disable in cs checker on r2xx commit 43b93fbffc2c080dba2e84df6fce8d7e6c0a2581 upstream. There are cases when multiple texture units have to be enabled, but not actually used to sample. This patch checks to see if the lookup_disable bit is set and if so, skips the texture check. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=25544 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/r100.c | 3 +++ drivers/gpu/drm/radeon/r100_track.h | 1 + drivers/gpu/drm/radeon/r200.c | 2 ++ drivers/gpu/drm/radeon/radeon_reg.h | 1 + 4 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 5c37c4884cf3..a3378ba2c5ce 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -3232,6 +3232,8 @@ static int r100_cs_track_texture_check(struct radeon_device *rdev, for (u = 0; u < track->num_texture; u++) { if (!track->textures[u].enabled) continue; + if (track->textures[u].lookup_disable) + continue; robj = track->textures[u].robj; if (robj == NULL) { DRM_ERROR("No texture bound to unit %u\n", u); @@ -3465,6 +3467,7 @@ void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track track->textures[i].robj = NULL; /* CS IB emission code makes sure texture unit are disabled */ track->textures[i].enabled = false; + track->textures[i].lookup_disable = false; track->textures[i].roundup_w = true; track->textures[i].roundup_h = true; if (track->separate_cube) diff --git a/drivers/gpu/drm/radeon/r100_track.h b/drivers/gpu/drm/radeon/r100_track.h index f47cdca1c004..af65600e6564 100644 --- a/drivers/gpu/drm/radeon/r100_track.h +++ b/drivers/gpu/drm/radeon/r100_track.h @@ -46,6 +46,7 @@ struct r100_cs_track_texture { unsigned height_11; bool use_pitch; bool enabled; + bool lookup_disable; bool roundup_w; bool roundup_h; unsigned compress_format; diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c index 0266d72e0a4c..d2408c395619 100644 --- a/drivers/gpu/drm/radeon/r200.c +++ b/drivers/gpu/drm/radeon/r200.c @@ -447,6 +447,8 @@ int r200_packet0_check(struct radeon_cs_parser *p, track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK); track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK); } + if (idx_value & R200_TXFORMAT_LOOKUP_DISABLE) + track->textures[i].lookup_disable = true; switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) { case R200_TXFORMAT_I8: case R200_TXFORMAT_RGB332: diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h index c332f46340d5..64928814de53 100644 --- a/drivers/gpu/drm/radeon/radeon_reg.h +++ b/drivers/gpu/drm/radeon/radeon_reg.h @@ -2836,6 +2836,7 @@ # define R200_TXFORMAT_ST_ROUTE_STQ5 (5 << 24) # define R200_TXFORMAT_ST_ROUTE_MASK (7 << 24) # define R200_TXFORMAT_ST_ROUTE_SHIFT 24 +# define R200_TXFORMAT_LOOKUP_DISABLE (1 << 27) # define R200_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28) # define R200_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29) # define R200_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30) -- cgit v1.2.3 From d428b23edbf023b941cbf54fed79a591a1348b32 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 7 Oct 2010 09:20:12 +0100 Subject: drm/i915: Free hardware status page on unload when physically mapped commit c2873e9633fe908dccd36dbb1d370e9c59a1ca62 upstream. A physically mapped hardware status page is allocated at driver load time but was never freed. Call the existing code to free this page at driver unload time on hardware which uses this kind. Signed-off-by: Keith Packard Signed-off-by: Andi Kleen [ickle: call before tearing down registers on KMS-only path, as pointed out by Dave Airlie] Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_dma.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index d396fe5915dd..bdd39fb96590 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -2297,6 +2297,9 @@ int i915_driver_unload(struct drm_device *dev) i915_gem_lastclose(dev); intel_cleanup_overlay(dev); + + if (!I915_NEED_GFX_HWS(dev)) + i915_free_hws(dev); } intel_teardown_mchbar(dev); -- cgit v1.2.3 From 46b77d237a5c4c393f5461729291030fc3e6e120 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 7 Oct 2010 16:01:25 -0700 Subject: drm/i915: diasable clock gating for the panel power sequencer commit 382b09362711d7d03272230a33767015a277926e upstream. Needed on Ibex Peak and Cougar Point or the panel won't always come on. Signed-off-by: Jesse Barnes Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_display.c | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index bed6a5eb4e99..140f01718631 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2709,6 +2709,9 @@ #define FDI_RXB_CHICKEN 0xc2010 #define FDI_RX_PHASE_SYNC_POINTER_ENABLE (1) +#define SOUTH_DSPCLK_GATE_D 0xc2020 +#define PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1<<29) + /* CPU: FDI_TX */ #define FDI_TXA_CTL 0x60100 #define FDI_TXB_CTL 0x61100 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d1c12435af48..660c67cac242 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5415,6 +5415,13 @@ void intel_init_clock_gating(struct drm_device *dev) I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); + /* + * On Ibex Peak and Cougar Point, we need to disable clock + * gating for the panel power sequencer or it will fail to + * start up when no ports are active. + */ + I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); + /* * According to the spec the following bits should be set in * order to enable memory self-refresh -- cgit v1.2.3 From 74cc0f389bb9401463ed7e8a0cbf580711dd9948 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 12 Aug 2010 09:35:00 +0100 Subject: drm/i915/overlay: Ensure that the reg_bo is in the GTT prior to writing. commit 0ddc1289f3ffd779779ddd3922f26ae7d0a21604 upstream. Just makes sure that writes are not being aliased by the CPU cache and do make it out to main memory. Signed-off-by: Chris Wilson Signed-off-by: Andi Kleen Reviewed-by: Daniel Vetter Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=24977 Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_overlay.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index fe05ba27440a..3d691c421ebc 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -1364,6 +1364,12 @@ void intel_setup_overlay(struct drm_device *dev) goto out_free_bo; } overlay->flip_addr = overlay->reg_bo->gtt_offset; + + ret = i915_gem_object_set_to_gtt_domain(reg_bo, true); + if (ret) { + DRM_ERROR("failed to move overlay register bo into the GTT\n"); + goto out_unpin_bo; + } } else { ret = i915_gem_attach_phys_object(dev, reg_bo, I915_GEM_PHYS_OVERLAY_REGS); @@ -1395,6 +1401,8 @@ void intel_setup_overlay(struct drm_device *dev) DRM_INFO("initialized overlay support\n"); return; +out_unpin_bo: + i915_gem_object_unpin(reg_bo); out_free_bo: drm_gem_object_unreference(reg_bo); out_free: -- cgit v1.2.3 From 63999a358efe5bae5b2c73c4107187e25f76943b Mon Sep 17 00:00:00 2001 From: Ken Kawasaki Date: Fri, 29 Oct 2010 12:17:51 +0000 Subject: pcnet_cs: add new_id commit 62391f97babb7fe0c769830b6f0e0bd184bd0704 upstream. pcnet_cs: add new_id: "corega Ether CF-TD" 10Base-T PCMCIA card. Signed-off-by: Ken Kawasaki Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/pcmcia/pcnet_cs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index bfdef72c5d5e..c5f1f25d4489 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -1602,6 +1602,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "FASTline PCMCIA 10/100 Fast-Ethernet", 0xfa2e424d, 0x3953d9b9), PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722), PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2), + PCMCIA_DEVICE_PROD_ID12("corega", "Ether CF-TD", 0x0a21501a, 0x6589340a), PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd), PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d), PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d), -- cgit v1.2.3 From 1219932ca26da2026e598590a3b7a2f36b3c3621 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 7 Oct 2010 14:08:52 +0100 Subject: SH: Add missing consts to sys_execve() declaration commit d8b5fc01683c66060edc202d6bb5635365822181 upstream. Add missing consts to the sys_execve() declaration which result in the following error: arch/sh/kernel/process_32.c:303: error: conflicting types for 'sys_execve' /warthog/nfs/linux-2.6-fscache/arch/sh/include/asm/syscalls_32.h:24: error: previous declaration of 'sys_execve' was here Signed-off-by: David Howells Cc: Nobuhiro Iwamatsu Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/sh/include/asm/syscalls_32.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sh/include/asm/syscalls_32.h b/arch/sh/include/asm/syscalls_32.h index 8b30200305c3..611e92d90475 100644 --- a/arch/sh/include/asm/syscalls_32.h +++ b/arch/sh/include/asm/syscalls_32.h @@ -19,8 +19,8 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs __regs); -asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv, - char __user * __user *uenvp, unsigned long r7, +asmlinkage int sys_execve(char __user *ufilename, const char __user * __user *uargv, + const char __user * __user *uenvp, unsigned long r7, struct pt_regs __regs); asmlinkage int sys_sigsuspend(old_sigset_t mask, unsigned long r5, unsigned long r6, unsigned long r7, -- cgit v1.2.3 From 0dbd161b08707ffddfdc2cd64ab762fef72311c9 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 24 Nov 2010 12:57:15 -0800 Subject: reiserfs: fix inode mutex - reiserfs lock misordering commit da905873effecd1c0166e578bc4b5006f041b18b upstream. reiserfs_unpack() locks the inode mutex with reiserfs_mutex_lock_safe() to protect against reiserfs lock dependency. However this protection requires to have the reiserfs lock to be locked. This is the case if reiserfs_unpack() is called by reiserfs_ioctl but not from reiserfs_quota_on() when it tries to unpack tails of quota files. Fix the ordering of the two locks in reiserfs_unpack() to fix this issue. Signed-off-by: Frederic Weisbecker Reported-by: Markus Gapp Reported-by: Jan Kara Cc: Jeff Mahoney Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/reiserfs/ioctl.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index 5cbb81e134ac..4131f4a49391 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c @@ -186,12 +186,11 @@ int reiserfs_unpack(struct inode *inode, struct file *filp) return 0; } - /* we need to make sure nobody is changing the file size beneath - ** us - */ - reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb); depth = reiserfs_write_lock_once(inode->i_sb); + /* we need to make sure nobody is changing the file size beneath us */ + reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb); + write_from = inode->i_size & (blocksize - 1); /* if we are on a block boundary, we are already unpacked. */ if (write_from == 0) { -- cgit v1.2.3 From e2d60d3b1a2aa3614fd385d81e90175cce0a3cbe Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 2 Dec 2010 14:31:16 -0800 Subject: reiserfs: don't acquire lock recursively in reiserfs_acl_chmod commit 238af8751f64a75f8b638193353b1c31ea32e738 upstream. reiserfs_acl_chmod() can be called by reiserfs_set_attr() and then take the reiserfs lock a second time. Thereafter it may call journal_begin() that definitely requires the lock not to be nested in order to release it before taking the journal mutex because the reiserfs lock depends on the journal mutex already. So, aviod nesting the lock in reiserfs_acl_chmod(). Reported-by: Pawel Zawora Signed-off-by: Frederic Weisbecker Tested-by: Pawel Zawora Cc: Jeff Mahoney Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/reiserfs/xattr_acl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 536d697a8a28..90d2fcb67a31 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -472,7 +472,9 @@ int reiserfs_acl_chmod(struct inode *inode) struct reiserfs_transaction_handle th; size_t size = reiserfs_xattr_nblocks(inode, reiserfs_acl_size(clone->a_count)); - reiserfs_write_lock(inode->i_sb); + int depth; + + depth = reiserfs_write_lock_once(inode->i_sb); error = journal_begin(&th, inode->i_sb, size * 2); if (!error) { int error2; @@ -482,7 +484,7 @@ int reiserfs_acl_chmod(struct inode *inode) if (error2) error = error2; } - reiserfs_write_unlock(inode->i_sb); + reiserfs_write_unlock_once(inode->i_sb, depth); } posix_acl_release(clone); return error; -- cgit v1.2.3 From 714cea953335738384f500f79131710d529c7583 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 28 Oct 2010 08:47:13 -0500 Subject: staging: rt2870: Add new USB ID for Belkin F6D4050 v1 commit 705059a670f3af2b37695e82de0ee58e75e656ed upstream. Add new USB ID for FT2870 for Belkin F6D4050 v1 Signed-off-by: Larry Finger Signed-off-by: Andi Kleen Reported- and Tested-by: James Long Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rt2860/usb_main_dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c index 12523921950a..2e5a407da34a 100644 --- a/drivers/staging/rt2860/usb_main_dev.c +++ b/drivers/staging/rt2860/usb_main_dev.c @@ -65,6 +65,7 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x14B2, 0x3C07)}, /* AL */ {USB_DEVICE(0x050D, 0x8053)}, /* Belkin */ {USB_DEVICE(0x050D, 0x825B)}, /* Belkin */ + {USB_DEVICE(0x050D, 0x935A)}, /* Belkin F6D4050 v1 */ {USB_DEVICE(0x050D, 0x935B)}, /* Belkin F6D4050 v2 */ {USB_DEVICE(0x14B2, 0x3C23)}, /* Airlink */ {USB_DEVICE(0x14B2, 0x3C27)}, /* Airlink */ -- cgit v1.2.3 From c2c9fa9f3eb11f8449beb413dadc154a37130fb1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Nov 2010 11:17:01 -0800 Subject: Staging: asus_oled: fix up some sysfs attribute permissions commit 590b0b9754bd8928926bae7194b6da7ead9bda3b upstream. They should not be writable by any user Reported-by: Linus Torvalds Cc: Jakub Schmidtke Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/asus_oled/asus_oled.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c index 5b279fb30f3f..003483b837f9 100644 --- a/drivers/staging/asus_oled/asus_oled.c +++ b/drivers/staging/asus_oled/asus_oled.c @@ -620,13 +620,13 @@ static ssize_t class_set_picture(struct device *device, #define ASUS_OLED_DEVICE_ATTR(_file) dev_attr_asus_oled_##_file -static DEVICE_ATTR(asus_oled_enabled, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(asus_oled_enabled, S_IRUSR | S_IRUGO, get_enabled, set_enabled); -static DEVICE_ATTR(asus_oled_picture, S_IWUGO , NULL, set_picture); +static DEVICE_ATTR(asus_oled_picture, S_IRUSR , NULL, set_picture); -static DEVICE_ATTR(enabled, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(enabled, S_IRUSR | S_IRUGO, class_get_enabled, class_set_enabled); -static DEVICE_ATTR(picture, S_IWUGO, NULL, class_set_picture); +static DEVICE_ATTR(picture, S_IRUSR, NULL, class_set_picture); static int asus_oled_probe(struct usb_interface *interface, const struct usb_device_id *id) -- cgit v1.2.3 From fa12a119fc79036eba048324c957eff23002d945 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 18 Nov 2010 11:21:04 -0800 Subject: Staging: asus_oled: fix up my fixup for some sysfs attribute permissions commit 515b4987ccd097cdf5416530b05fdf9e01afe95a upstream. They should be writable by root, not readable. Doh, stupid me with the wrong flags. Reported-by: Jonathan Cameron Cc: Jakub Schmidtke Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/asus_oled/asus_oled.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c index 003483b837f9..62445551eecf 100644 --- a/drivers/staging/asus_oled/asus_oled.c +++ b/drivers/staging/asus_oled/asus_oled.c @@ -620,13 +620,13 @@ static ssize_t class_set_picture(struct device *device, #define ASUS_OLED_DEVICE_ATTR(_file) dev_attr_asus_oled_##_file -static DEVICE_ATTR(asus_oled_enabled, S_IRUSR | S_IRUGO, +static DEVICE_ATTR(asus_oled_enabled, S_IWUSR | S_IRUGO, get_enabled, set_enabled); -static DEVICE_ATTR(asus_oled_picture, S_IRUSR , NULL, set_picture); +static DEVICE_ATTR(asus_oled_picture, S_IWUSR , NULL, set_picture); -static DEVICE_ATTR(enabled, S_IRUSR | S_IRUGO, +static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO, class_get_enabled, class_set_enabled); -static DEVICE_ATTR(picture, S_IRUSR, NULL, class_set_picture); +static DEVICE_ATTR(picture, S_IWUSR, NULL, class_set_picture); static int asus_oled_probe(struct usb_interface *interface, const struct usb_device_id *id) -- cgit v1.2.3 From 74a099583418727faca5ec6f79c60e3922b697f1 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Sun, 21 Nov 2010 14:01:14 -0500 Subject: ALSA: hda: Use hp-laptop quirk to enable headphones automute for Asus A52J commit 673f7a8984c3a9e2cb1108ce221da1ebbd9e5d09 upstream. BugLink: https://launchpad.net/bugs/677652 The original reporter states that, in 2.6.35, headphones do not appear to work, nor does inserting them mute the A52J's onboard speakers. Upon inspecting the codec dump, it appears that the newly committed hp-laptop quirk will suffice to enable this basic functionality. Testing was done with an alsa-driver build from 2010-11-21. Reported-and-tested-by: Joan Creus Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_conexant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 15ba418fe6a4..53418b490290 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3033,6 +3033,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), + SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_HP_LAPTOP), SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), -- cgit v1.2.3 From c2f4c8e83521d6be0ecc8ece52172ab1dd550b68 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Nov 2010 11:23:33 -0800 Subject: Staging: line6: fix up some sysfs attribute permissions commit 2018845b6a169f75341f8e68ad1089cb6697cf24 and 2018845b6a169f75341f8e68ad1089cb6697cf24 upstream merged together as it had to be backported by hand. They should not be writable by any user Reported-by: Linus Torvalds Cc: Markus Grabner Cc: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/line6/control.c | 204 +++++++++++++++++++-------------------- drivers/staging/line6/midi.c | 4 +- drivers/staging/line6/pod.c | 32 +++--- drivers/staging/line6/toneport.c | 4 +- drivers/staging/line6/variax.c | 12 +-- 5 files changed, 128 insertions(+), 128 deletions(-) diff --git a/drivers/staging/line6/control.c b/drivers/staging/line6/control.c index 0b598526de62..e414571938a3 100644 --- a/drivers/staging/line6/control.c +++ b/drivers/staging/line6/control.c @@ -268,210 +268,210 @@ VARIAX_PARAM_R(float, mix2); VARIAX_PARAM_R(float, mix1); VARIAX_PARAM_R(int, pickup_wiring); -static DEVICE_ATTR(tweak, S_IWUGO | S_IRUGO, pod_get_tweak, pod_set_tweak); -static DEVICE_ATTR(wah_position, S_IWUGO | S_IRUGO, pod_get_wah_position, +static DEVICE_ATTR(tweak, S_IWUSR | S_IRUGO, pod_get_tweak, pod_set_tweak); +static DEVICE_ATTR(wah_position, S_IWUSR | S_IRUGO, pod_get_wah_position, pod_set_wah_position); -static DEVICE_ATTR(compression_gain, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(compression_gain, S_IWUSR | S_IRUGO, pod_get_compression_gain, pod_set_compression_gain); -static DEVICE_ATTR(vol_pedal_position, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(vol_pedal_position, S_IWUSR | S_IRUGO, pod_get_vol_pedal_position, pod_set_vol_pedal_position); -static DEVICE_ATTR(compression_threshold, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(compression_threshold, S_IWUSR | S_IRUGO, pod_get_compression_threshold, pod_set_compression_threshold); -static DEVICE_ATTR(pan, S_IWUGO | S_IRUGO, pod_get_pan, pod_set_pan); -static DEVICE_ATTR(amp_model_setup, S_IWUGO | S_IRUGO, pod_get_amp_model_setup, +static DEVICE_ATTR(pan, S_IWUSR | S_IRUGO, pod_get_pan, pod_set_pan); +static DEVICE_ATTR(amp_model_setup, S_IWUSR | S_IRUGO, pod_get_amp_model_setup, pod_set_amp_model_setup); -static DEVICE_ATTR(amp_model, S_IWUGO | S_IRUGO, pod_get_amp_model, +static DEVICE_ATTR(amp_model, S_IWUSR | S_IRUGO, pod_get_amp_model, pod_set_amp_model); -static DEVICE_ATTR(drive, S_IWUGO | S_IRUGO, pod_get_drive, pod_set_drive); -static DEVICE_ATTR(bass, S_IWUGO | S_IRUGO, pod_get_bass, pod_set_bass); -static DEVICE_ATTR(mid, S_IWUGO | S_IRUGO, pod_get_mid, pod_set_mid); -static DEVICE_ATTR(lowmid, S_IWUGO | S_IRUGO, pod_get_lowmid, pod_set_lowmid); -static DEVICE_ATTR(treble, S_IWUGO | S_IRUGO, pod_get_treble, pod_set_treble); -static DEVICE_ATTR(highmid, S_IWUGO | S_IRUGO, pod_get_highmid, +static DEVICE_ATTR(drive, S_IWUSR | S_IRUGO, pod_get_drive, pod_set_drive); +static DEVICE_ATTR(bass, S_IWUSR | S_IRUGO, pod_get_bass, pod_set_bass); +static DEVICE_ATTR(mid, S_IWUSR | S_IRUGO, pod_get_mid, pod_set_mid); +static DEVICE_ATTR(lowmid, S_IWUSR | S_IRUGO, pod_get_lowmid, pod_set_lowmid); +static DEVICE_ATTR(treble, S_IWUSR | S_IRUGO, pod_get_treble, pod_set_treble); +static DEVICE_ATTR(highmid, S_IWUSR | S_IRUGO, pod_get_highmid, pod_set_highmid); -static DEVICE_ATTR(chan_vol, S_IWUGO | S_IRUGO, pod_get_chan_vol, +static DEVICE_ATTR(chan_vol, S_IWUSR | S_IRUGO, pod_get_chan_vol, pod_set_chan_vol); -static DEVICE_ATTR(reverb_mix, S_IWUGO | S_IRUGO, pod_get_reverb_mix, +static DEVICE_ATTR(reverb_mix, S_IWUSR | S_IRUGO, pod_get_reverb_mix, pod_set_reverb_mix); -static DEVICE_ATTR(effect_setup, S_IWUGO | S_IRUGO, pod_get_effect_setup, +static DEVICE_ATTR(effect_setup, S_IWUSR | S_IRUGO, pod_get_effect_setup, pod_set_effect_setup); -static DEVICE_ATTR(band_1_frequency, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(band_1_frequency, S_IWUSR | S_IRUGO, pod_get_band_1_frequency, pod_set_band_1_frequency); -static DEVICE_ATTR(presence, S_IWUGO | S_IRUGO, pod_get_presence, +static DEVICE_ATTR(presence, S_IWUSR | S_IRUGO, pod_get_presence, pod_set_presence); -static DEVICE_ATTR2(treble__bass, treble, S_IWUGO | S_IRUGO, +static DEVICE_ATTR2(treble__bass, treble, S_IWUSR | S_IRUGO, pod_get_treble__bass, pod_set_treble__bass); -static DEVICE_ATTR(noise_gate_enable, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(noise_gate_enable, S_IWUSR | S_IRUGO, pod_get_noise_gate_enable, pod_set_noise_gate_enable); -static DEVICE_ATTR(gate_threshold, S_IWUGO | S_IRUGO, pod_get_gate_threshold, +static DEVICE_ATTR(gate_threshold, S_IWUSR | S_IRUGO, pod_get_gate_threshold, pod_set_gate_threshold); -static DEVICE_ATTR(gate_decay_time, S_IWUGO | S_IRUGO, pod_get_gate_decay_time, +static DEVICE_ATTR(gate_decay_time, S_IWUSR | S_IRUGO, pod_get_gate_decay_time, pod_set_gate_decay_time); -static DEVICE_ATTR(stomp_enable, S_IWUGO | S_IRUGO, pod_get_stomp_enable, +static DEVICE_ATTR(stomp_enable, S_IWUSR | S_IRUGO, pod_get_stomp_enable, pod_set_stomp_enable); -static DEVICE_ATTR(comp_enable, S_IWUGO | S_IRUGO, pod_get_comp_enable, +static DEVICE_ATTR(comp_enable, S_IWUSR | S_IRUGO, pod_get_comp_enable, pod_set_comp_enable); -static DEVICE_ATTR(stomp_time, S_IWUGO | S_IRUGO, pod_get_stomp_time, +static DEVICE_ATTR(stomp_time, S_IWUSR | S_IRUGO, pod_get_stomp_time, pod_set_stomp_time); -static DEVICE_ATTR(delay_enable, S_IWUGO | S_IRUGO, pod_get_delay_enable, +static DEVICE_ATTR(delay_enable, S_IWUSR | S_IRUGO, pod_get_delay_enable, pod_set_delay_enable); -static DEVICE_ATTR(mod_param_1, S_IWUGO | S_IRUGO, pod_get_mod_param_1, +static DEVICE_ATTR(mod_param_1, S_IWUSR | S_IRUGO, pod_get_mod_param_1, pod_set_mod_param_1); -static DEVICE_ATTR(delay_param_1, S_IWUGO | S_IRUGO, pod_get_delay_param_1, +static DEVICE_ATTR(delay_param_1, S_IWUSR | S_IRUGO, pod_get_delay_param_1, pod_set_delay_param_1); -static DEVICE_ATTR(delay_param_1_note_value, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(delay_param_1_note_value, S_IWUSR | S_IRUGO, pod_get_delay_param_1_note_value, pod_set_delay_param_1_note_value); -static DEVICE_ATTR2(band_2_frequency__bass, band_2_frequency, S_IWUGO | S_IRUGO, +static DEVICE_ATTR2(band_2_frequency__bass, band_2_frequency, S_IWUSR | S_IRUGO, pod_get_band_2_frequency__bass, pod_set_band_2_frequency__bass); -static DEVICE_ATTR(delay_param_2, S_IWUGO | S_IRUGO, pod_get_delay_param_2, +static DEVICE_ATTR(delay_param_2, S_IWUSR | S_IRUGO, pod_get_delay_param_2, pod_set_delay_param_2); -static DEVICE_ATTR(delay_volume_mix, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(delay_volume_mix, S_IWUSR | S_IRUGO, pod_get_delay_volume_mix, pod_set_delay_volume_mix); -static DEVICE_ATTR(delay_param_3, S_IWUGO | S_IRUGO, pod_get_delay_param_3, +static DEVICE_ATTR(delay_param_3, S_IWUSR | S_IRUGO, pod_get_delay_param_3, pod_set_delay_param_3); -static DEVICE_ATTR(reverb_enable, S_IWUGO | S_IRUGO, pod_get_reverb_enable, +static DEVICE_ATTR(reverb_enable, S_IWUSR | S_IRUGO, pod_get_reverb_enable, pod_set_reverb_enable); -static DEVICE_ATTR(reverb_type, S_IWUGO | S_IRUGO, pod_get_reverb_type, +static DEVICE_ATTR(reverb_type, S_IWUSR | S_IRUGO, pod_get_reverb_type, pod_set_reverb_type); -static DEVICE_ATTR(reverb_decay, S_IWUGO | S_IRUGO, pod_get_reverb_decay, +static DEVICE_ATTR(reverb_decay, S_IWUSR | S_IRUGO, pod_get_reverb_decay, pod_set_reverb_decay); -static DEVICE_ATTR(reverb_tone, S_IWUGO | S_IRUGO, pod_get_reverb_tone, +static DEVICE_ATTR(reverb_tone, S_IWUSR | S_IRUGO, pod_get_reverb_tone, pod_set_reverb_tone); -static DEVICE_ATTR(reverb_pre_delay, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(reverb_pre_delay, S_IWUSR | S_IRUGO, pod_get_reverb_pre_delay, pod_set_reverb_pre_delay); -static DEVICE_ATTR(reverb_pre_post, S_IWUGO | S_IRUGO, pod_get_reverb_pre_post, +static DEVICE_ATTR(reverb_pre_post, S_IWUSR | S_IRUGO, pod_get_reverb_pre_post, pod_set_reverb_pre_post); -static DEVICE_ATTR(band_2_frequency, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(band_2_frequency, S_IWUSR | S_IRUGO, pod_get_band_2_frequency, pod_set_band_2_frequency); -static DEVICE_ATTR2(band_3_frequency__bass, band_3_frequency, S_IWUGO | S_IRUGO, +static DEVICE_ATTR2(band_3_frequency__bass, band_3_frequency, S_IWUSR | S_IRUGO, pod_get_band_3_frequency__bass, pod_set_band_3_frequency__bass); -static DEVICE_ATTR(wah_enable, S_IWUGO | S_IRUGO, pod_get_wah_enable, +static DEVICE_ATTR(wah_enable, S_IWUSR | S_IRUGO, pod_get_wah_enable, pod_set_wah_enable); -static DEVICE_ATTR(modulation_lo_cut, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(modulation_lo_cut, S_IWUSR | S_IRUGO, pod_get_modulation_lo_cut, pod_set_modulation_lo_cut); -static DEVICE_ATTR(delay_reverb_lo_cut, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(delay_reverb_lo_cut, S_IWUSR | S_IRUGO, pod_get_delay_reverb_lo_cut, pod_set_delay_reverb_lo_cut); -static DEVICE_ATTR(volume_pedal_minimum, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(volume_pedal_minimum, S_IWUSR | S_IRUGO, pod_get_volume_pedal_minimum, pod_set_volume_pedal_minimum); -static DEVICE_ATTR(eq_pre_post, S_IWUGO | S_IRUGO, pod_get_eq_pre_post, +static DEVICE_ATTR(eq_pre_post, S_IWUSR | S_IRUGO, pod_get_eq_pre_post, pod_set_eq_pre_post); -static DEVICE_ATTR(volume_pre_post, S_IWUGO | S_IRUGO, pod_get_volume_pre_post, +static DEVICE_ATTR(volume_pre_post, S_IWUSR | S_IRUGO, pod_get_volume_pre_post, pod_set_volume_pre_post); -static DEVICE_ATTR(di_model, S_IWUGO | S_IRUGO, pod_get_di_model, +static DEVICE_ATTR(di_model, S_IWUSR | S_IRUGO, pod_get_di_model, pod_set_di_model); -static DEVICE_ATTR(di_delay, S_IWUGO | S_IRUGO, pod_get_di_delay, +static DEVICE_ATTR(di_delay, S_IWUSR | S_IRUGO, pod_get_di_delay, pod_set_di_delay); -static DEVICE_ATTR(mod_enable, S_IWUGO | S_IRUGO, pod_get_mod_enable, +static DEVICE_ATTR(mod_enable, S_IWUSR | S_IRUGO, pod_get_mod_enable, pod_set_mod_enable); -static DEVICE_ATTR(mod_param_1_note_value, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(mod_param_1_note_value, S_IWUSR | S_IRUGO, pod_get_mod_param_1_note_value, pod_set_mod_param_1_note_value); -static DEVICE_ATTR(mod_param_2, S_IWUGO | S_IRUGO, pod_get_mod_param_2, +static DEVICE_ATTR(mod_param_2, S_IWUSR | S_IRUGO, pod_get_mod_param_2, pod_set_mod_param_2); -static DEVICE_ATTR(mod_param_3, S_IWUGO | S_IRUGO, pod_get_mod_param_3, +static DEVICE_ATTR(mod_param_3, S_IWUSR | S_IRUGO, pod_get_mod_param_3, pod_set_mod_param_3); -static DEVICE_ATTR(mod_param_4, S_IWUGO | S_IRUGO, pod_get_mod_param_4, +static DEVICE_ATTR(mod_param_4, S_IWUSR | S_IRUGO, pod_get_mod_param_4, pod_set_mod_param_4); -static DEVICE_ATTR(mod_param_5, S_IWUGO | S_IRUGO, pod_get_mod_param_5, +static DEVICE_ATTR(mod_param_5, S_IWUSR | S_IRUGO, pod_get_mod_param_5, pod_set_mod_param_5); -static DEVICE_ATTR(mod_volume_mix, S_IWUGO | S_IRUGO, pod_get_mod_volume_mix, +static DEVICE_ATTR(mod_volume_mix, S_IWUSR | S_IRUGO, pod_get_mod_volume_mix, pod_set_mod_volume_mix); -static DEVICE_ATTR(mod_pre_post, S_IWUGO | S_IRUGO, pod_get_mod_pre_post, +static DEVICE_ATTR(mod_pre_post, S_IWUSR | S_IRUGO, pod_get_mod_pre_post, pod_set_mod_pre_post); -static DEVICE_ATTR(modulation_model, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(modulation_model, S_IWUSR | S_IRUGO, pod_get_modulation_model, pod_set_modulation_model); -static DEVICE_ATTR(band_3_frequency, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(band_3_frequency, S_IWUSR | S_IRUGO, pod_get_band_3_frequency, pod_set_band_3_frequency); -static DEVICE_ATTR2(band_4_frequency__bass, band_4_frequency, S_IWUGO | S_IRUGO, +static DEVICE_ATTR2(band_4_frequency__bass, band_4_frequency, S_IWUSR | S_IRUGO, pod_get_band_4_frequency__bass, pod_set_band_4_frequency__bass); -static DEVICE_ATTR(mod_param_1_double_precision, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(mod_param_1_double_precision, S_IWUSR | S_IRUGO, pod_get_mod_param_1_double_precision, pod_set_mod_param_1_double_precision); -static DEVICE_ATTR(delay_param_1_double_precision, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(delay_param_1_double_precision, S_IWUSR | S_IRUGO, pod_get_delay_param_1_double_precision, pod_set_delay_param_1_double_precision); -static DEVICE_ATTR(eq_enable, S_IWUGO | S_IRUGO, pod_get_eq_enable, +static DEVICE_ATTR(eq_enable, S_IWUSR | S_IRUGO, pod_get_eq_enable, pod_set_eq_enable); -static DEVICE_ATTR(tap, S_IWUGO | S_IRUGO, pod_get_tap, pod_set_tap); -static DEVICE_ATTR(volume_tweak_pedal_assign, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(tap, S_IWUSR | S_IRUGO, pod_get_tap, pod_set_tap); +static DEVICE_ATTR(volume_tweak_pedal_assign, S_IWUSR | S_IRUGO, pod_get_volume_tweak_pedal_assign, pod_set_volume_tweak_pedal_assign); -static DEVICE_ATTR(band_5_frequency, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(band_5_frequency, S_IWUSR | S_IRUGO, pod_get_band_5_frequency, pod_set_band_5_frequency); -static DEVICE_ATTR(tuner, S_IWUGO | S_IRUGO, pod_get_tuner, pod_set_tuner); -static DEVICE_ATTR(mic_selection, S_IWUGO | S_IRUGO, pod_get_mic_selection, +static DEVICE_ATTR(tuner, S_IWUSR | S_IRUGO, pod_get_tuner, pod_set_tuner); +static DEVICE_ATTR(mic_selection, S_IWUSR | S_IRUGO, pod_get_mic_selection, pod_set_mic_selection); -static DEVICE_ATTR(cabinet_model, S_IWUGO | S_IRUGO, pod_get_cabinet_model, +static DEVICE_ATTR(cabinet_model, S_IWUSR | S_IRUGO, pod_get_cabinet_model, pod_set_cabinet_model); -static DEVICE_ATTR(stomp_model, S_IWUGO | S_IRUGO, pod_get_stomp_model, +static DEVICE_ATTR(stomp_model, S_IWUSR | S_IRUGO, pod_get_stomp_model, pod_set_stomp_model); -static DEVICE_ATTR(roomlevel, S_IWUGO | S_IRUGO, pod_get_roomlevel, +static DEVICE_ATTR(roomlevel, S_IWUSR | S_IRUGO, pod_get_roomlevel, pod_set_roomlevel); -static DEVICE_ATTR(band_4_frequency, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(band_4_frequency, S_IWUSR | S_IRUGO, pod_get_band_4_frequency, pod_set_band_4_frequency); -static DEVICE_ATTR(band_6_frequency, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(band_6_frequency, S_IWUSR | S_IRUGO, pod_get_band_6_frequency, pod_set_band_6_frequency); -static DEVICE_ATTR(stomp_param_1_note_value, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(stomp_param_1_note_value, S_IWUSR | S_IRUGO, pod_get_stomp_param_1_note_value, pod_set_stomp_param_1_note_value); -static DEVICE_ATTR(stomp_param_2, S_IWUGO | S_IRUGO, pod_get_stomp_param_2, +static DEVICE_ATTR(stomp_param_2, S_IWUSR | S_IRUGO, pod_get_stomp_param_2, pod_set_stomp_param_2); -static DEVICE_ATTR(stomp_param_3, S_IWUGO | S_IRUGO, pod_get_stomp_param_3, +static DEVICE_ATTR(stomp_param_3, S_IWUSR | S_IRUGO, pod_get_stomp_param_3, pod_set_stomp_param_3); -static DEVICE_ATTR(stomp_param_4, S_IWUGO | S_IRUGO, pod_get_stomp_param_4, +static DEVICE_ATTR(stomp_param_4, S_IWUSR | S_IRUGO, pod_get_stomp_param_4, pod_set_stomp_param_4); -static DEVICE_ATTR(stomp_param_5, S_IWUGO | S_IRUGO, pod_get_stomp_param_5, +static DEVICE_ATTR(stomp_param_5, S_IWUSR | S_IRUGO, pod_get_stomp_param_5, pod_set_stomp_param_5); -static DEVICE_ATTR(stomp_param_6, S_IWUGO | S_IRUGO, pod_get_stomp_param_6, +static DEVICE_ATTR(stomp_param_6, S_IWUSR | S_IRUGO, pod_get_stomp_param_6, pod_set_stomp_param_6); -static DEVICE_ATTR(amp_switch_select, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(amp_switch_select, S_IWUSR | S_IRUGO, pod_get_amp_switch_select, pod_set_amp_switch_select); -static DEVICE_ATTR(delay_param_4, S_IWUGO | S_IRUGO, pod_get_delay_param_4, +static DEVICE_ATTR(delay_param_4, S_IWUSR | S_IRUGO, pod_get_delay_param_4, pod_set_delay_param_4); -static DEVICE_ATTR(delay_param_5, S_IWUGO | S_IRUGO, pod_get_delay_param_5, +static DEVICE_ATTR(delay_param_5, S_IWUSR | S_IRUGO, pod_get_delay_param_5, pod_set_delay_param_5); -static DEVICE_ATTR(delay_pre_post, S_IWUGO | S_IRUGO, pod_get_delay_pre_post, +static DEVICE_ATTR(delay_pre_post, S_IWUSR | S_IRUGO, pod_get_delay_pre_post, pod_set_delay_pre_post); -static DEVICE_ATTR(delay_model, S_IWUGO | S_IRUGO, pod_get_delay_model, +static DEVICE_ATTR(delay_model, S_IWUSR | S_IRUGO, pod_get_delay_model, pod_set_delay_model); -static DEVICE_ATTR(delay_verb_model, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(delay_verb_model, S_IWUSR | S_IRUGO, pod_get_delay_verb_model, pod_set_delay_verb_model); -static DEVICE_ATTR(tempo_msb, S_IWUGO | S_IRUGO, pod_get_tempo_msb, +static DEVICE_ATTR(tempo_msb, S_IWUSR | S_IRUGO, pod_get_tempo_msb, pod_set_tempo_msb); -static DEVICE_ATTR(tempo_lsb, S_IWUGO | S_IRUGO, pod_get_tempo_lsb, +static DEVICE_ATTR(tempo_lsb, S_IWUSR | S_IRUGO, pod_get_tempo_lsb, pod_set_tempo_lsb); -static DEVICE_ATTR(wah_model, S_IWUGO | S_IRUGO, pod_get_wah_model, +static DEVICE_ATTR(wah_model, S_IWUSR | S_IRUGO, pod_get_wah_model, pod_set_wah_model); -static DEVICE_ATTR(bypass_volume, S_IWUGO | S_IRUGO, pod_get_bypass_volume, +static DEVICE_ATTR(bypass_volume, S_IWUSR | S_IRUGO, pod_get_bypass_volume, pod_set_bypass_volume); -static DEVICE_ATTR(fx_loop_on_off, S_IWUGO | S_IRUGO, pod_get_fx_loop_on_off, +static DEVICE_ATTR(fx_loop_on_off, S_IWUSR | S_IRUGO, pod_get_fx_loop_on_off, pod_set_fx_loop_on_off); -static DEVICE_ATTR(tweak_param_select, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(tweak_param_select, S_IWUSR | S_IRUGO, pod_get_tweak_param_select, pod_set_tweak_param_select); -static DEVICE_ATTR(amp1_engage, S_IWUGO | S_IRUGO, pod_get_amp1_engage, +static DEVICE_ATTR(amp1_engage, S_IWUSR | S_IRUGO, pod_get_amp1_engage, pod_set_amp1_engage); -static DEVICE_ATTR(band_1_gain, S_IWUGO | S_IRUGO, pod_get_band_1_gain, +static DEVICE_ATTR(band_1_gain, S_IWUSR | S_IRUGO, pod_get_band_1_gain, pod_set_band_1_gain); -static DEVICE_ATTR2(band_2_gain__bass, band_2_gain, S_IWUGO | S_IRUGO, +static DEVICE_ATTR2(band_2_gain__bass, band_2_gain, S_IWUSR | S_IRUGO, pod_get_band_2_gain__bass, pod_set_band_2_gain__bass); -static DEVICE_ATTR(band_2_gain, S_IWUGO | S_IRUGO, pod_get_band_2_gain, +static DEVICE_ATTR(band_2_gain, S_IWUSR | S_IRUGO, pod_get_band_2_gain, pod_set_band_2_gain); -static DEVICE_ATTR2(band_3_gain__bass, band_3_gain, S_IWUGO | S_IRUGO, +static DEVICE_ATTR2(band_3_gain__bass, band_3_gain, S_IWUSR | S_IRUGO, pod_get_band_3_gain__bass, pod_set_band_3_gain__bass); -static DEVICE_ATTR(band_3_gain, S_IWUGO | S_IRUGO, pod_get_band_3_gain, +static DEVICE_ATTR(band_3_gain, S_IWUSR | S_IRUGO, pod_get_band_3_gain, pod_set_band_3_gain); -static DEVICE_ATTR2(band_4_gain__bass, band_4_gain, S_IWUGO | S_IRUGO, +static DEVICE_ATTR2(band_4_gain__bass, band_4_gain, S_IWUSR | S_IRUGO, pod_get_band_4_gain__bass, pod_set_band_4_gain__bass); -static DEVICE_ATTR2(band_5_gain__bass, band_5_gain, S_IWUGO | S_IRUGO, +static DEVICE_ATTR2(band_5_gain__bass, band_5_gain, S_IWUSR | S_IRUGO, pod_get_band_5_gain__bass, pod_set_band_5_gain__bass); -static DEVICE_ATTR(band_4_gain, S_IWUGO | S_IRUGO, pod_get_band_4_gain, +static DEVICE_ATTR(band_4_gain, S_IWUSR | S_IRUGO, pod_get_band_4_gain, pod_set_band_4_gain); -static DEVICE_ATTR2(band_6_gain__bass, band_6_gain, S_IWUGO | S_IRUGO, +static DEVICE_ATTR2(band_6_gain__bass, band_6_gain, S_IWUSR | S_IRUGO, pod_get_band_6_gain__bass, pod_set_band_6_gain__bass); static DEVICE_ATTR(body, S_IRUGO, variax_get_body, line6_nop_write); static DEVICE_ATTR(pickup1_enable, S_IRUGO, variax_get_pickup1_enable, diff --git a/drivers/staging/line6/midi.c b/drivers/staging/line6/midi.c index 32b6ca75cadb..9b42e34763f1 100644 --- a/drivers/staging/line6/midi.c +++ b/drivers/staging/line6/midi.c @@ -362,8 +362,8 @@ static ssize_t midi_set_midi_mask_receive(struct device *dev, return count; } -static DEVICE_ATTR(midi_mask_transmit, S_IWUGO | S_IRUGO, midi_get_midi_mask_transmit, midi_set_midi_mask_transmit); -static DEVICE_ATTR(midi_mask_receive, S_IWUGO | S_IRUGO, midi_get_midi_mask_receive, midi_set_midi_mask_receive); +static DEVICE_ATTR(midi_mask_transmit, S_IWUSR | S_IRUGO, midi_get_midi_mask_transmit, midi_set_midi_mask_transmit); +static DEVICE_ATTR(midi_mask_receive, S_IWUSR | S_IRUGO, midi_get_midi_mask_receive, midi_set_midi_mask_receive); /* MIDI device destructor */ static int snd_line6_midi_free(struct snd_device *device) diff --git a/drivers/staging/line6/pod.c b/drivers/staging/line6/pod.c index 28f514611abc..63318d717cd7 100644 --- a/drivers/staging/line6/pod.c +++ b/drivers/staging/line6/pod.c @@ -952,33 +952,33 @@ POD_GET_SYSTEM_PARAM(tuner_pitch, 1, 1); #undef GET_SYSTEM_PARAM /* POD special files: */ -static DEVICE_ATTR(channel, S_IWUGO | S_IRUGO, pod_get_channel, pod_set_channel); +static DEVICE_ATTR(channel, S_IWUSR | S_IRUGO, pod_get_channel, pod_set_channel); static DEVICE_ATTR(clip, S_IRUGO, pod_wait_for_clip, line6_nop_write); static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write); static DEVICE_ATTR(dirty, S_IRUGO, pod_get_dirty, line6_nop_write); -static DEVICE_ATTR(dump, S_IWUGO | S_IRUGO, pod_get_dump, pod_set_dump); -static DEVICE_ATTR(dump_buf, S_IWUGO | S_IRUGO, pod_get_dump_buf, pod_set_dump_buf); -static DEVICE_ATTR(finish, S_IWUGO, line6_nop_read, pod_set_finish); +static DEVICE_ATTR(dump, S_IWUSR | S_IRUGO, pod_get_dump, pod_set_dump); +static DEVICE_ATTR(dump_buf, S_IWUSR | S_IRUGO, pod_get_dump_buf, pod_set_dump_buf); +static DEVICE_ATTR(finish, S_IWUSR, line6_nop_read, pod_set_finish); static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version, line6_nop_write); -static DEVICE_ATTR(midi_postprocess, S_IWUGO | S_IRUGO, pod_get_midi_postprocess, pod_set_midi_postprocess); -static DEVICE_ATTR(monitor_level, S_IWUGO | S_IRUGO, pod_get_monitor_level, pod_set_monitor_level); +static DEVICE_ATTR(midi_postprocess, S_IWUSR | S_IRUGO, pod_get_midi_postprocess, pod_set_midi_postprocess); +static DEVICE_ATTR(monitor_level, S_IWUSR | S_IRUGO, pod_get_monitor_level, pod_set_monitor_level); static DEVICE_ATTR(name, S_IRUGO, pod_get_name, line6_nop_write); static DEVICE_ATTR(name_buf, S_IRUGO, pod_get_name_buf, line6_nop_write); -static DEVICE_ATTR(retrieve_amp_setup, S_IWUGO, line6_nop_read, pod_set_retrieve_amp_setup); -static DEVICE_ATTR(retrieve_channel, S_IWUGO, line6_nop_read, pod_set_retrieve_channel); -static DEVICE_ATTR(retrieve_effects_setup, S_IWUGO, line6_nop_read, pod_set_retrieve_effects_setup); -static DEVICE_ATTR(routing, S_IWUGO | S_IRUGO, pod_get_routing, pod_set_routing); +static DEVICE_ATTR(retrieve_amp_setup, S_IWUSR, line6_nop_read, pod_set_retrieve_amp_setup); +static DEVICE_ATTR(retrieve_channel, S_IWUSR, line6_nop_read, pod_set_retrieve_channel); +static DEVICE_ATTR(retrieve_effects_setup, S_IWUSR, line6_nop_read, pod_set_retrieve_effects_setup); +static DEVICE_ATTR(routing, S_IWUSR | S_IRUGO, pod_get_routing, pod_set_routing); static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number, line6_nop_write); -static DEVICE_ATTR(store_amp_setup, S_IWUGO, line6_nop_read, pod_set_store_amp_setup); -static DEVICE_ATTR(store_channel, S_IWUGO, line6_nop_read, pod_set_store_channel); -static DEVICE_ATTR(store_effects_setup, S_IWUGO, line6_nop_read, pod_set_store_effects_setup); -static DEVICE_ATTR(tuner_freq, S_IWUGO | S_IRUGO, pod_get_tuner_freq, pod_set_tuner_freq); -static DEVICE_ATTR(tuner_mute, S_IWUGO | S_IRUGO, pod_get_tuner_mute, pod_set_tuner_mute); +static DEVICE_ATTR(store_amp_setup, S_IWUSR, line6_nop_read, pod_set_store_amp_setup); +static DEVICE_ATTR(store_channel, S_IWUSR, line6_nop_read, pod_set_store_channel); +static DEVICE_ATTR(store_effects_setup, S_IWUSR, line6_nop_read, pod_set_store_effects_setup); +static DEVICE_ATTR(tuner_freq, S_IWUSR | S_IRUGO, pod_get_tuner_freq, pod_set_tuner_freq); +static DEVICE_ATTR(tuner_mute, S_IWUSR | S_IRUGO, pod_get_tuner_mute, pod_set_tuner_mute); static DEVICE_ATTR(tuner_note, S_IRUGO, pod_get_tuner_note, line6_nop_write); static DEVICE_ATTR(tuner_pitch, S_IRUGO, pod_get_tuner_pitch, line6_nop_write); #if CREATE_RAW_FILE -static DEVICE_ATTR(raw, S_IWUGO, line6_nop_read, line6_set_raw); +static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw); #endif /* diff --git a/drivers/staging/line6/toneport.c b/drivers/staging/line6/toneport.c index e6770ea17936..db421781d550 100644 --- a/drivers/staging/line6/toneport.c +++ b/drivers/staging/line6/toneport.c @@ -124,9 +124,9 @@ static ssize_t toneport_set_led_green(struct device *dev, return count; } -static DEVICE_ATTR(led_red, S_IWUGO | S_IRUGO, line6_nop_read, +static DEVICE_ATTR(led_red, S_IWUSR | S_IRUGO, line6_nop_read, toneport_set_led_red); -static DEVICE_ATTR(led_green, S_IWUGO | S_IRUGO, line6_nop_read, +static DEVICE_ATTR(led_green, S_IWUSR | S_IRUGO, line6_nop_read, toneport_set_led_green); static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2) diff --git a/drivers/staging/line6/variax.c b/drivers/staging/line6/variax.c index 58ddbe6393ff..b2fc09b05939 100644 --- a/drivers/staging/line6/variax.c +++ b/drivers/staging/line6/variax.c @@ -389,17 +389,17 @@ static ssize_t variax_set_raw2(struct device *dev, #endif /* Variax workbench special files: */ -static DEVICE_ATTR(model, S_IWUGO | S_IRUGO, variax_get_model, variax_set_model); -static DEVICE_ATTR(volume, S_IWUGO | S_IRUGO, variax_get_volume, variax_set_volume); -static DEVICE_ATTR(tone, S_IWUGO | S_IRUGO, variax_get_tone, variax_set_tone); +static DEVICE_ATTR(model, S_IWUSR | S_IRUGO, variax_get_model, variax_set_model); +static DEVICE_ATTR(volume, S_IWUSR | S_IRUGO, variax_get_volume, variax_set_volume); +static DEVICE_ATTR(tone, S_IWUSR | S_IRUGO, variax_get_tone, variax_set_tone); static DEVICE_ATTR(name, S_IRUGO, variax_get_name, line6_nop_write); static DEVICE_ATTR(bank, S_IRUGO, variax_get_bank, line6_nop_write); static DEVICE_ATTR(dump, S_IRUGO, variax_get_dump, line6_nop_write); -static DEVICE_ATTR(active, S_IWUGO | S_IRUGO, variax_get_active, variax_set_active); +static DEVICE_ATTR(active, S_IWUSR | S_IRUGO, variax_get_active, variax_set_active); #if CREATE_RAW_FILE -static DEVICE_ATTR(raw, S_IWUGO, line6_nop_read, line6_set_raw); -static DEVICE_ATTR(raw2, S_IWUGO, line6_nop_read, variax_set_raw2); +static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw); +static DEVICE_ATTR(raw2, S_IWUSR, line6_nop_read, variax_set_raw2); #endif -- cgit v1.2.3 From 676564419927a29c5dbdd074dbbce44dc50e1d03 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 26 Oct 2010 14:22:13 -0700 Subject: hpet: fix unwanted interrupt due to stale irq status bit commit 96e9694df446d1154ec2f4fdba8908588b9cba38 upstream. Jaswinder Singh Rajput wrote: > By executing Documentation/timers/hpet_example.c > > for polling, I requested for 3 iterations but it seems iteration work > for only 2 as first expired time is always very small. > > # ./hpet_example poll /dev/hpet 10 3 > -hpet: executing poll > hpet_poll: info.hi_flags 0x0 > hpet_poll: expired time = 0x13 > hpet_poll: revents = 0x1 > hpet_poll: data 0x1 > hpet_poll: expired time = 0x1868c > hpet_poll: revents = 0x1 > hpet_poll: data 0x1 > hpet_poll: expired time = 0x18645 > hpet_poll: revents = 0x1 > hpet_poll: data 0x1 Clearing the HPET interrupt enable bit disables interrupt generation but does not disable the timer, so the interrupt status bit will still be set when the timer elapses. If another interrupt arrives before the timer has been correctly programmed (due to some other device on the same interrupt line, or CONFIG_DEBUG_SHIRQ), this results in an extra unwanted interrupt event because the status bit is likely to be set from comparator matches that happened before the device was opened. Therefore, we have to ensure that the interrupt status bit is and stays cleared until we actually program the timer. Signed-off-by: Clemens Ladisch Reported-by: Jaswinder Singh Rajput Cc: Ingo Molnar Cc: Thomas Gleixner Cc: john stultz Cc: Bob Picco Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/char/hpet.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index a0a1829d3198..995d2ff487d9 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -479,6 +479,21 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp) if (irq) { unsigned long irq_flags; + if (devp->hd_flags & HPET_SHARED_IRQ) { + /* + * To prevent the interrupt handler from seeing an + * unwanted interrupt status bit, program the timer + * so that it will not fire in the near future ... + */ + writel(readl(&timer->hpet_config) & ~Tn_TYPE_CNF_MASK, + &timer->hpet_config); + write_counter(read_counter(&hpet->hpet_mc), + &timer->hpet_compare); + /* ... and clear any left-over status. */ + isr = 1 << (devp - devp->hd_hpets->hp_dev); + writel(isr, &hpet->hpet_isr); + } + sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev)); irq_flags = devp->hd_flags & HPET_SHARED_IRQ ? IRQF_SHARED : IRQF_DISABLED; -- cgit v1.2.3 From f38e82fdf2a2e201f188b9d48b145284ab38f74c Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 26 Oct 2010 14:22:11 -0700 Subject: hpet: unmap unused I/O space commit a56d5318716d120e040294bb258901ba89fb9c90 upstream. When the initialization code in hpet finds a memory resource and does not find an IRQ, it does not unmap the memory resource previously mapped. There are buggy BIOSes which report resources exactly like this and what is worse the memory region bases point to normal RAM. This normally would not matter since the space is not touched. But when PAT is turned on, ioremap causes the page to be uncached and sets this bit in page->flags. Then when the page is about to be used by the allocator, it is reported as: BUG: Bad page state in process md5sum pfn:3ed00 page:ffffea0000dbd800 count:0 mapcount:0 mapping:(null) index:0x0 page flags: 0x20000001000000(uncached) Pid: 7956, comm: md5sum Not tainted 2.6.34-12-desktop #1 Call Trace: [] bad_page+0xb1/0x100 [] prep_new_page+0x1a5/0x1c0 [] get_page_from_freelist+0x3a1/0x640 [] __alloc_pages_nodemask+0x10f/0x6b0 ... In this particular case: 1) HPET returns 3ed00000 as memory region base, but it is not in reserved ranges reported by the BIOS (excerpt): BIOS-e820: 0000000000100000 - 00000000af6cf000 (usable) BIOS-e820: 00000000af6cf000 - 00000000afdcf000 (reserved) 2) there is no IRQ resource reported by HPET method. On the other hand, the Intel HPET specs (1.0a) says (3.2.5.1): _CRS ( // Report 1K of memory consumed by this Timer Block memory range consumed // Optional: only used if BIOS allocates Interrupts [1] IRQs consumed ) [1] For case where Timer Block is configured to consume IRQ0/IRQ8 AND Legacy 8254/Legacy RTC hardware still exists, the device objects associated with 8254 & RTC devices should not report IRQ0/IRQ8 as "consumed resources". So in theory we should check whether if it is the case and use those interrupts instead. Anyway the address reported by the BIOS here is bogus, so non-presence of IRQ doesn't mean the "optional" part in point 2). Since I got no reply previously, fix this by simply unmapping the space when IRQ is not found and memory region was mapped previously. It would be probably more safe to walk the resources again and unmap appropriately depending on type. But as we now use only ioremap for both 2 memory resource types, it is not necessarily needed right now. Addresses https://bugzilla.novell.com/show_bug.cgi?id=629908 Reported-by: Olaf Hering Signed-off-by: Jiri Slaby Acked-by: Clemens Ladisch Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/char/hpet.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 995d2ff487d9..f8e7d89ceb2c 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -985,6 +985,8 @@ static int hpet_acpi_add(struct acpi_device *device) return -ENODEV; if (!data.hd_address || !data.hd_nirqs) { + if (data.hd_address) + iounmap(data.hd_address); printk("%s: no address or irqs in _CRS\n", __func__); return -ENODEV; } -- cgit v1.2.3 From 992c78f9f294b8dfc72c783fce9b83151407cf74 Mon Sep 17 00:00:00 2001 From: "Richard A. Smith" Date: Sat, 25 Sep 2010 19:19:26 +0100 Subject: olpc_battery: Fix endian neutral breakage for s16 values commit 7cfbb29466633e6ecdc14f76a693c8478c2b22af upstream. When the driver was updated to be endian neutral (8e9c7716c) the signed part of the s16 values was lost. This is because be16_to_cpu() returns an unsigned value. This patch casts the values back to a s16 number prior to the the implicit cast up to an int. Signed-off-by: Richard A. Smith Signed-off-by: Daniel Drake Signed-off-by: Anton Vorontsov Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/power/olpc_battery.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c index baefcf1cffc9..efa71cd957ef 100644 --- a/drivers/power/olpc_battery.c +++ b/drivers/power/olpc_battery.c @@ -271,14 +271,14 @@ static int olpc_bat_get_property(struct power_supply *psy, if (ret) return ret; - val->intval = (int)be16_to_cpu(ec_word) * 9760L / 32; + val->intval = (s16)be16_to_cpu(ec_word) * 9760L / 32; break; case POWER_SUPPLY_PROP_CURRENT_AVG: ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2); if (ret) return ret; - val->intval = (int)be16_to_cpu(ec_word) * 15625L / 120; + val->intval = (s16)be16_to_cpu(ec_word) * 15625L / 120; break; case POWER_SUPPLY_PROP_CAPACITY: ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1); @@ -299,7 +299,7 @@ static int olpc_bat_get_property(struct power_supply *psy, if (ret) return ret; - val->intval = (int)be16_to_cpu(ec_word) * 100 / 256; + val->intval = (s16)be16_to_cpu(ec_word) * 100 / 256; break; case POWER_SUPPLY_PROP_TEMP_AMBIENT: ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2); @@ -313,7 +313,7 @@ static int olpc_bat_get_property(struct power_supply *psy, if (ret) return ret; - val->intval = (int)be16_to_cpu(ec_word) * 6250 / 15; + val->intval = (s16)be16_to_cpu(ec_word) * 6250 / 15; break; case POWER_SUPPLY_PROP_SERIAL_NUMBER: ret = olpc_ec_cmd(EC_BAT_SERIAL, NULL, 0, (void *)&ser_buf, 8); -- cgit v1.2.3 From 41ba4ea6ba426acc9a6eb18abfde5e1c1287563a Mon Sep 17 00:00:00 2001 From: Masanori ITOH Date: Tue, 26 Oct 2010 14:21:20 -0700 Subject: percpu: fix list_head init bug in __percpu_counter_init() commit 8474b591faf3bb0a1e08a60d21d6baac498f15e4 upstream. WARNING: at lib/list_debug.c:26 __list_add+0x3f/0x81() Hardware name: Express5800/B120a [N8400-085] list_add corruption. next->prev should be prev (ffffffff81a7ea00), but was dead000000200200. (next=ffff88080b872d58). Modules linked in: aoe ipt_MASQUERADE iptable_nat nf_nat autofs4 sunrpc bridge 8021q garp stp llc ipv6 cpufreq_ondemand acpi_cpufreq freq_table dm_round_robin dm_multipath kvm_intel kvm uinput lpfc scsi_transport_fc igb ioatdma scsi_tgt i2c_i801 i2c_core dca iTCO_wdt iTCO_vendor_support pcspkr shpchp megaraid_sas [last unloaded: aoe] Pid: 54, comm: events/3 Tainted: G W 2.6.34-vanilla1 #1 Call Trace: [] warn_slowpath_common+0x7c/0x94 [] warn_slowpath_fmt+0x41/0x43 [] __list_add+0x3f/0x81 [] __percpu_counter_init+0x59/0x6b [] bdi_init+0x118/0x17e [] blk_alloc_queue_node+0x79/0x143 [] blk_alloc_queue+0x11/0x13 [] aoeblk_gdalloc+0x8e/0x1c9 [aoe] [] aoecmd_sleepwork+0x25/0xa8 [aoe] [] worker_thread+0x1a9/0x237 [] ? aoecmd_sleepwork+0x0/0xa8 [aoe] [] ? autoremove_wake_function+0x0/0x39 [] ? worker_thread+0x0/0x237 [] kthread+0x7f/0x87 [] kernel_thread_helper+0x4/0x10 [] ? kthread+0x0/0x87 [] ? kernel_thread_helper+0x0/0x10 It's because there is no initialization code for a list_head contained in the struct backing_dev_info under CONFIG_HOTPLUG_CPU, and the bug comes up when block device drivers calling blk_alloc_queue() are used. In case of me, I got them by using aoe. Signed-off-by: Masanori Itoh Cc: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- lib/percpu_counter.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c index aeaa6d734447..9d942128c152 100644 --- a/lib/percpu_counter.c +++ b/lib/percpu_counter.c @@ -76,6 +76,7 @@ int __percpu_counter_init(struct percpu_counter *fbc, s64 amount, if (!fbc->counters) return -ENOMEM; #ifdef CONFIG_HOTPLUG_CPU + INIT_LIST_HEAD(&fbc->list); mutex_lock(&percpu_counters_lock); list_add(&fbc->list, &percpu_counters); mutex_unlock(&percpu_counters_lock); -- cgit v1.2.3 From 00997af69e7e5b447cc163a4084990f0caeeb1ae Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 26 Oct 2010 14:21:17 -0700 Subject: ipmi: proper spinlock initialization commit de5e2ddf9bb3ce7b643223b9b0718062254f302f upstream. Unloading ipmi module can trigger following error. (if CONFIG_DEBUG_SPINLOCK=y) [ 9633.779590] BUG: spinlock bad magic on CPU#1, rmmod/7170 [ 9633.779606] lock: f41f5414, .magic: 00000000, .owner: /-1, .owner_cpu: 0 [ 9633.779626] Pid: 7170, comm: rmmod Not tainted 2.6.36-rc7-11474-gb71eb1e-dirty #328 [ 9633.779644] Call Trace: [ 9633.779657] [] ? printk+0x18/0x1c [ 9633.779672] [] spin_bug+0xa3/0xf0 [ 9633.779685] [] do_raw_spin_lock+0x7d/0x160 [ 9633.779702] [] ? release_sysfs_dirent+0x47/0xb0 [ 9633.779718] [] ? sysfs_addrm_finish+0xa8/0xd0 [ 9633.779734] [] _raw_spin_lock_irqsave+0xc/0x20 [ 9633.779752] [] cleanup_one_si+0x6a/0x200 [ipmi_si] [ 9633.779768] [] ? sysfs_hash_and_remove+0x72/0x80 [ 9633.779786] [] ipmi_pnp_remove+0xd/0xf [ipmi_si] [ 9633.779802] [] pnp_device_remove+0x1b/0x40 Fix this by initializing spinlocks in a smi_info_alloc() helper function, right after memory allocation and clearing. Signed-off-by: Eric Dumazet Acked-by: David Miller Cc: Yinghai Lu Acked-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/char/ipmi/ipmi_si_intf.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index ff68e7c34ce7..b1a30143ac37 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -1662,6 +1662,17 @@ static int check_hotmod_int_op(const char *curr, const char *option, return 0; } +static struct smi_info *smi_info_alloc(void) +{ + struct smi_info *info = kzalloc(sizeof(*info), GFP_KERNEL); + + if (info) { + spin_lock_init(&info->si_lock); + spin_lock_init(&info->msg_lock); + } + return info; +} + static int hotmod_handler(const char *val, struct kernel_param *kp) { char *str = kstrdup(val, GFP_KERNEL); @@ -1776,7 +1787,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) } if (op == HM_ADD) { - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = smi_info_alloc(); if (!info) { rv = -ENOMEM; goto out; @@ -1838,7 +1849,7 @@ static __devinit void hardcode_find_bmc(void) if (!ports[i] && !addrs[i]) continue; - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = smi_info_alloc(); if (!info) return; @@ -2025,7 +2036,7 @@ static __devinit int try_init_spmi(struct SPMITable *spmi) else addr_space = IPMI_IO_ADDR_SPACE; - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = smi_info_alloc(); if (!info) { printk(KERN_ERR PFX "Could not allocate SI data (3)\n"); return -ENOMEM; @@ -2129,7 +2140,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, if (!acpi_dev) return -ENODEV; - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = smi_info_alloc(); if (!info) return -ENOMEM; @@ -2307,7 +2318,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) { struct smi_info *info; - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = smi_info_alloc(); if (!info) { printk(KERN_ERR PFX "Could not allocate SI data\n"); return; @@ -2408,7 +2419,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK; struct smi_info *info; - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = smi_info_alloc(); if (!info) return -ENOMEM; @@ -2546,7 +2557,7 @@ static int __devinit ipmi_of_probe(struct of_device *dev, return -EINVAL; } - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = smi_info_alloc(); if (!info) { dev_err(&dev->dev, @@ -2988,7 +2999,7 @@ static __devinit void default_find_bmc(void) if (check_legacy_ioport(ipmi_defaults[i].port)) continue; #endif - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = smi_info_alloc(); if (!info) return; @@ -3111,9 +3122,6 @@ static int try_smi_init(struct smi_info *new_smi) goto out_err; } - spin_lock_init(&(new_smi->si_lock)); - spin_lock_init(&(new_smi->msg_lock)); - /* Do low-level detection first. */ if (new_smi->handlers->detect(new_smi->si_sm)) { if (new_smi->addr_source) -- cgit v1.2.3 From f876b27b05022df0c0ab813ea72ae5106f34a79c Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 26 Oct 2010 14:21:16 -0700 Subject: um: remove PAGE_SIZE alignment in linker script causing kernel segfault. commit 6915e04f8847bea16d0890f559694ad8eedd026c upstream. The linker script cleanup that I did in commit 5d150a97f93 ("um: Clean up linker script using standard macros.") (2.6.32) accidentally introduced an ALIGN(PAGE_SIZE) when converting to use INIT_TEXT_SECTION; Richard Weinberger reported that this causes the kernel to segfault with CONFIG_STATIC_LINK=y. I'm not certain why this extra alignment is a problem, but it seems likely it is because previously __init_begin = _stext = _text = _sinittext and with the extra ALIGN(PAGE_SIZE), _sinittext becomes different from the rest. So there is likely a bug here where something is assuming that _sinittext is the same as one of those other symbols. But reverting the accidental change fixes the regression, so it seems worth committing that now. Signed-off-by: Tim Abbott Reported-by: Richard Weinberger Cc: Jeff Dike Signed-off-by: Andi Kleen Tested by: Antoine Martin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/um/kernel/uml.lds.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index ec6378550671..9a873d765615 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S @@ -22,7 +22,7 @@ SECTIONS _text = .; _stext = .; __init_begin = .; - INIT_TEXT_SECTION(PAGE_SIZE) + INIT_TEXT_SECTION(0) . = ALIGN(PAGE_SIZE); .text : -- cgit v1.2.3 From cfa9f4a158d8c5fc0033798491bfcc9b8fe2619e Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 26 Oct 2010 14:21:13 -0700 Subject: um: fix global timer issue when using CONFIG_NO_HZ commit 482db6df1746c4fa7d64a2441d4cb2610249c679 upstream. This fixes a issue which was introduced by fe2cc53e ("uml: track and make up lost ticks"). timeval_to_ns() returns long long and not int. Due to that UML's timer did not work properlt and caused timer freezes. Signed-off-by: Richard Weinberger Acked-by: Pekka Enberg Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/um/os-Linux/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index dec5678fc17f..6e3359d6a839 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c @@ -60,7 +60,7 @@ static inline long long timeval_to_ns(const struct timeval *tv) long long disable_timer(void) { struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } }); - int remain, max = UM_NSEC_PER_SEC / UM_HZ; + long long remain, max = UM_NSEC_PER_SEC / UM_HZ; if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0) printk(UM_KERN_ERR "disable_timer - setitimer failed, " -- cgit v1.2.3 From 6b4100ddcb000aab7cbb86a66361989d1e87a1c3 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Oct 2010 19:33:43 +0200 Subject: numa: fix slab_node(MPOL_BIND) commit 800416f799e0723635ac2d720ad4449917a1481c upstream. When a node contains only HighMem memory, slab_node(MPOL_BIND) dereferences a NULL pointer. [ This code seems to go back all the way to commit 19770b32609b: "mm: filter based on a nodemask as well as a gfp_mask". Which was back in April 2008, and it got merged into 2.6.26. - Linus ] Signed-off-by: Eric Dumazet Cc: Mel Gorman Cc: Christoph Lameter Cc: Lee Schermerhorn Cc: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- mm/mempolicy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 5bc0a96beb51..407cda2d753f 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1576,7 +1576,7 @@ unsigned slab_node(struct mempolicy *policy) (void)first_zones_zonelist(zonelist, highest_zoneidx, &policy->v.nodes, &zone); - return zone->node; + return zone ? zone->node : numa_node_id(); } default: -- cgit v1.2.3 From ec76a70ac2f733b36f71866935071b0ba1ff95de Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 28 Oct 2010 20:31:50 +0200 Subject: hwmon: (lm85) Fix ADT7468 frequency table commit fa7a5797e57d2ed71f9a6fb44f0ae42c2d7b74b7 upstream. The ADT7468 uses the same frequency table as the ADT7463. Signed-off-by: Jean Delvare Cc: Darrick J. Wong Acked-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/hwmon/lm85.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index b3841a615595..2e8f0c9458d4 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -1259,6 +1259,7 @@ static int lm85_probe(struct i2c_client *client, switch (data->type) { case adm1027: case adt7463: + case adt7468: case emc6d100: case emc6d102: data->freq_map = adm1027_freq_map; -- cgit v1.2.3 From 5b28c745f7fd51718315cec9e4d34204c2513ca4 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Wed, 27 Oct 2010 11:17:15 -0400 Subject: oprofile: Fix the hang while taking the cpu offline commit 4ac3dbec800d93485a5c84e37af676278eea657c upstream. The kernel build with CONFIG_OPROFILE and CPU_HOTPLUG enabled. The oprofile is initialised using system timer in absence of hardware counters supports. Oprofile isn't started from userland. In this setup while doing a CPU offline the kernel hangs in infinite for loop inside lock_hrtimer_base() function This happens because as part of oprofile_cpu_notify(, it tries to stop an hrtimer which was never started. These per-cpu hrtimers are started when the oprfile is started. echo 1 > /dev/oprofile/enable This problem also existwhen the cpu is booted with maxcpus parameter set. When bringing the remaining cpus online the timers are started even if oprofile is not yet enabled. This patch fix this issue by adding a state variable so that these hrtimer start/stop is only attempted when oprofile is started For stable kernels v2.6.35.y and v2.6.36.y. Reported-by: Jan Sebastien Tested-by: sricharan Signed-off-by: Santosh Shilimkar Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/oprofile/timer_int.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c index dc0ae4d14dff..010725117dbb 100644 --- a/drivers/oprofile/timer_int.c +++ b/drivers/oprofile/timer_int.c @@ -21,6 +21,7 @@ #include "oprof.h" static DEFINE_PER_CPU(struct hrtimer, oprofile_hrtimer); +static int ctr_running; static enum hrtimer_restart oprofile_hrtimer_notify(struct hrtimer *hrtimer) { @@ -33,6 +34,9 @@ static void __oprofile_hrtimer_start(void *unused) { struct hrtimer *hrtimer = &__get_cpu_var(oprofile_hrtimer); + if (!ctr_running) + return; + hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer->function = oprofile_hrtimer_notify; @@ -42,7 +46,10 @@ static void __oprofile_hrtimer_start(void *unused) static int oprofile_hrtimer_start(void) { + get_online_cpus(); + ctr_running = 1; on_each_cpu(__oprofile_hrtimer_start, NULL, 1); + put_online_cpus(); return 0; } @@ -50,6 +57,9 @@ static void __oprofile_hrtimer_stop(int cpu) { struct hrtimer *hrtimer = &per_cpu(oprofile_hrtimer, cpu); + if (!ctr_running) + return; + hrtimer_cancel(hrtimer); } @@ -57,8 +67,11 @@ static void oprofile_hrtimer_stop(void) { int cpu; + get_online_cpus(); for_each_online_cpu(cpu) __oprofile_hrtimer_stop(cpu); + ctr_running = 0; + put_online_cpus(); } static int __cpuinit oprofile_cpu_notify(struct notifier_block *self, -- cgit v1.2.3 From 83e28dfc81d705b795a1fe80fb33db194fb8ba71 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Tue, 26 Oct 2010 14:21:10 -0700 Subject: mm: fix return value of scan_lru_pages in memory unplug commit f8f72ad5396987e05a42cf7eff826fb2a15ff148 upstream. scan_lru_pages returns pfn. So, it's type should be "unsigned long" not "int". Note: I guess this has been work until now because memory hotplug tester's machine has not very big memory.... physical address < 32bit << PAGE_SHIFT. Reported-by: KOSAKI Motohiro Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andi Kleen Reviewed-by: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/memory_hotplug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index dd186c1a5d53..6345dfe78d2c 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -659,7 +659,7 @@ static int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn) * Scanning pfn is much easier than scanning lru list. * Scan pfn from start to end and Find LRU page. */ -int scan_lru_pages(unsigned long start, unsigned long end) +unsigned long scan_lru_pages(unsigned long start, unsigned long end) { unsigned long pfn; struct page *page; -- cgit v1.2.3 From 02ab02c2d3425ea6c358c6d56a9c6087d5cd3812 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 26 Oct 2010 14:21:11 -0700 Subject: mm, page-allocator: do not check the state of a non-existant buddy during free commit b7f50cfa3630b6e079929ffccfd442d65064ee1f upstream. There is a bug in commit 6dda9d55 ("page allocator: reduce fragmentation in buddy allocator by adding buddies that are merging to the tail of the free lists") that means a buddy at order MAX_ORDER is checked for merging. A page of this order never exists so at times, an effectively random piece of memory is being checked. Alan Curry has reported that this is causing memory corruption in userspace data on a PPC32 platform (http://lkml.org/lkml/2010/10/9/32). It is not clear why this is happening. It could be a cache coherency problem where pages mapped in both user and kernel space are getting Signed-off-by: Andi Kleen different cache lines due to the bad read from kernel space (http://lkml.org/lkml/2010/10/13/179). It could also be that there are some special registers being io-remapped at the end of the memmap array and that a read has special meaning on them. Compiler bugs have been ruled out because the assembly before and after the patch looks relatively harmless. This patch fixes the problem by ensuring we are not reading a possibly invalid location of memory. It's not clear why the read causes corruption but one way or the other it is a buggy read. Signed-off-by: Mel Gorman Cc: Corrado Zoccolo Reported-by: Alan Curry Cc: KOSAKI Motohiro Cc: Christoph Lameter Cc: Rik van Riel 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(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index f7cc624085cc..3390da65f161 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -530,7 +530,7 @@ static inline void __free_one_page(struct page *page, * so it's less likely to be used soon and more likely to be merged * as a higher order page */ - if ((order < MAX_ORDER-1) && pfn_valid_within(page_to_pfn(buddy))) { + if ((order < MAX_ORDER-2) && pfn_valid_within(page_to_pfn(buddy))) { struct page *higher_page, *higher_buddy; combined_idx = __find_combined_index(page_idx, order); higher_page = page + combined_idx - page_idx; -- cgit v1.2.3 From 73227d4e29941ea157ff5786294877e938fe48e1 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Tue, 26 Oct 2010 14:22:08 -0700 Subject: mm: fix is_mem_section_removable() page_order BUG_ON check commit 572438f9b52236bd8938b1647cc15e027d27ef55 upstream. page_order() is called by memory hotplug's user interface to check the section is removable or not. (is_mem_section_removable()) It calls page_order() withoug holding zone->lock. So, even if the caller does if (PageBuddy(page)) ret = page_order(page) ... The caller may hit BUG_ON(). For fixing this, there are 2 choices. 1. add zone->lock. 2. remove BUG_ON(). is_mem_section_removable() is used for some "advice" and doesn't need to be 100% accurate. This is_removable() can be called via user program.. We don't want to take this important lock for long by user's request. So, this patch removes BUG_ON(). Signed-off-by: KAMEZAWA Hiroyuki Acked-by: Wu Fengguang Acked-by: Michal Hocko Acked-by: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- mm/internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/internal.h b/mm/internal.h index 6a697bb97fc5..dedb0aff673f 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -62,7 +62,7 @@ extern bool is_free_buddy_page(struct page *page); */ static inline unsigned long page_order(struct page *page) { - VM_BUG_ON(!PageBuddy(page)); + /* PageBuddy() must be checked by the caller */ return page_private(page); } -- cgit v1.2.3 From 836263b61726f425f472f5659898db6ec1426dad Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 14 Oct 2010 16:30:41 +0100 Subject: agp/intel: Also add B43.1 to list of supported devices commit 3dde04b0152634d42994b34b86bbf3c70fbc6b19 upstream. This was a missing piece from 41a5142 that dropped recognition of the AGP module for the second B43 variant. Reported-by: Stefan Bader Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/char/agp/intel-agp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 41871211e5d1..e38fe2be1071 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -1048,6 +1048,7 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_G45_HB), ID(PCI_DEVICE_ID_INTEL_G41_HB), 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_M_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), -- cgit v1.2.3 From b0c97dcc33e8d95e3fd4ed21bee7d7fc6733ef85 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 28 Oct 2010 10:43:26 -0500 Subject: b43: Fix warning at drivers/mmc/core/core.c:237 in mmc_wait_for_cmd commit 9f2a0fac625bcef9c579bcf0b0c904ab1a56e7c4 upstream. On module removal, the sdio version of b43 generates the following warning: [ 851.560519] ------------[ cut here ]------------ [ 851.560531] WARNING: at drivers/mmc/core/core.c:237 mmc_wait_for_cmd+0x88/0x90() [ 851.560534] Hardware name: 20552PG [ 851.560536] Modules linked in: b43(-) ssb mmc_block binfmt_misc rfcomm sco bnep ppdev l2cap ipt_MASQUERADE iptable_nat nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_state nf_conntrack ipt_REJECT xt_tcpudp iptable_filter ip_tables x_tables bridge stp kvm_intel kvm arc4 iwlagn snd_hda_codec_conexant snd_hda_intel snd_hda_codec iwlcore snd_hwdep snd_pcm thinkpad_acpi mac80211 snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq r852 joydev snd_timer sm_common pcmcia nand snd_seq_device cfg80211 sdhci_pci btusb psmouse tpm_tis yenta_socket nand_ids lp snd pcmcia_rsrc nand_ecc bluetooth sdhci tpm pcmcia_core parport mtd snd_page_alloc serio_raw tpm_bios soundcore nvram led_class sha256_generic aes_i586 aes_generic dm_crypt i915 drm_kms_helper drm ahci intel_agp i2c_algo_bit intel_gtt e1000e libahci video agpgart output [ 851.560620] Pid: 2504, comm: rmmod Not tainted 2.6.36-titan0+ #1 [ 851.560622] Call Trace: [ 851.560631] [] warn_slowpath_common+0x72/0xa0 [ 851.560636] [] ? mmc_wait_for_cmd+0x88/0x90 [ 851.560641] [] ? mmc_wait_for_cmd+0x88/0x90 [ 851.560645] [] warn_slowpath_null+0x22/0x30 [ 851.560649] [] mmc_wait_for_cmd+0x88/0x90 [ 851.560655] [] ? device_release+0x25/0x80 [ 851.560660] [] mmc_io_rw_direct_host+0xa0/0x150 [ 851.560665] [] mmc_io_rw_direct+0x30/0x40 [ 851.560669] [] sdio_disable_func+0x37/0xa0 [ 851.560683] [] b43_sdio_remove+0x30/0x50 [b43] [ 851.560687] [] sdio_bus_remove+0x1c/0x60 [ 851.560692] [] ? blocking_notifier_call_chain+0x1f/0x30 [ 851.560697] [] __device_release_driver+0x51/0xb0 [ 851.560701] [] driver_detach+0x8f/0xa0 [ 851.560705] [] bus_remove_driver+0x63/0xa0 [ 851.560709] [] driver_unregister+0x49/0x80 [ 851.560713] [] ? driver_unregister+0x49/0x80 [ 851.560718] [] sdio_unregister_driver+0x17/0x20 [ 851.560727] [] b43_sdio_exit+0x12/0x20 [b43] [ 851.560734] [] b43_exit+0x17/0x3c [b43] [ 851.560740] [] sys_delete_module+0x13d/0x200 [ 851.560747] [] ? do_munmap+0x212/0x300 [ 851.560752] [] sysenter_do_call+0x12/0x28 [ 851.560757] ---[ end trace 31e14488072d2f7d ]--- [ 851.560759] ------------[ cut here ]------------ The warning is caused by b43 not claiming the device before calling sdio_disable_func(). Signed-off-by: Larry Finger Reported-by: Arnd Hannemann Tested-by: Arnd Hannemann Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/b43/sdio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c index 4e56b7bbcebd..8b1831454381 100644 --- a/drivers/net/wireless/b43/sdio.c +++ b/drivers/net/wireless/b43/sdio.c @@ -175,7 +175,9 @@ static void b43_sdio_remove(struct sdio_func *func) struct b43_sdio *sdio = sdio_get_drvdata(func); ssb_bus_unregister(&sdio->ssb); + sdio_claim_host(func); sdio_disable_func(func); + sdio_release_host(func); kfree(sdio); sdio_set_drvdata(func, NULL); } -- cgit v1.2.3 From 1a6880a22a0f92677b5e2a71ac96ab2ea24c219e Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 23 Nov 2010 17:10:24 +0100 Subject: wireless: b43: fix error path in SDIO commit e476a5a41ad67d0e2b4a652820c49a3923eb936b upstream. Fix unbalanced call to sdio_release_host() on the error path. Signed-off-by: Guennadi Liakhovetski Acked-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/b43/sdio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c index 8b1831454381..4808dc7044f8 100644 --- a/drivers/net/wireless/b43/sdio.c +++ b/drivers/net/wireless/b43/sdio.c @@ -163,6 +163,7 @@ static int b43_sdio_probe(struct sdio_func *func, err_free_ssb: kfree(sdio); err_disable_func: + sdio_claim_host(func); sdio_disable_func(func); err_release_host: sdio_release_host(func); -- cgit v1.2.3 From 2c48711c32475054d08c0574ebff24573611f9f9 Mon Sep 17 00:00:00 2001 From: Daniel Klaffenbach Date: Fri, 19 Nov 2010 21:25:21 -0600 Subject: ssb: b43-pci-bridge: Add new vendor for BCM4318 commit 1d8638d4038eb8709edc80e37a0bbb77253d86e9 upstream. Add new vendor for Broadcom 4318. Signed-off-by: Daniel Klaffenbach Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/ssb/b43_pci_bridge.c | 1 + include/linux/pci_ids.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c index ef9c6a04ad8f..744d3f6e4709 100644 --- a/drivers/ssb/b43_pci_bridge.c +++ b/drivers/ssb/b43_pci_bridge.c @@ -24,6 +24,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4312) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4315) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4318) }, + { PCI_DEVICE(PCI_VENDOR_ID_BCM_GVC, 0x4318) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) }, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index aa702055cd6e..f1cbd85ad5ec 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2038,6 +2038,7 @@ #define PCI_DEVICE_ID_AFAVLAB_P030 0x2182 #define PCI_SUBDEVICE_ID_AFAVLAB_P061 0x2150 +#define PCI_VENDOR_ID_BCM_GVC 0x14a4 #define PCI_VENDOR_ID_BROADCOM 0x14e4 #define PCI_DEVICE_ID_TIGON3_5752 0x1600 #define PCI_DEVICE_ID_TIGON3_5752M 0x1601 -- cgit v1.2.3 From 2ff4e4e9ee1d1575be941f5c1c9409a02e74927f Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 26 Oct 2010 14:21:16 -0700 Subject: drivers/misc/ad525x_dpot.c: fix typo in spi write16 and write24 transfer counts commit 1f9fa5216eacf4fdf9d3e4ab57feb8b642f0e78b upstream. This is a bug fix. Some SPI connected devices using 16/24 bit accesses, previously failed, now work. This typo slipped in after testing, during some restructuring. Signed-off-by: Michael Hennerich Cc: Mike Frysinger Cc: Chris Verges Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/misc/ad525x_dpot-spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c index b8c6df9c8437..6cfcb636577a 100644 --- a/drivers/misc/ad525x_dpot-spi.c +++ b/drivers/misc/ad525x_dpot-spi.c @@ -53,13 +53,13 @@ static int write8(void *client, u8 val) static int write16(void *client, u8 reg, u8 val) { u8 data[2] = {reg, val}; - return spi_write(client, data, 1); + return spi_write(client, data, 2); } static int write24(void *client, u8 reg, u16 val) { u8 data[3] = {reg, val >> 8, val}; - return spi_write(client, data, 1); + return spi_write(client, data, 3); } static int read8(void *client) -- cgit v1.2.3 From 63fa5ec8afa814e33a73db404db64fc88cc5749d Mon Sep 17 00:00:00 2001 From: "Robin@sgi.com" Date: Wed, 24 Nov 2010 12:56:59 -0800 Subject: sgi-xpc: XPC fails to discover partitions with all nasids above 128 commit c22c7aeff69796f46ae0fcec141538e28f50b24e upstream. UV hardware defines 256 memory protection regions versus the baseline 64 with increasing size for the SN2 ia64. This was overlooked when XPC was modified to accomodate both UV and SN2. Without this patch, a user could reconfigure their existing system and suddenly disable cross-partition communications with no indication of what has gone wrong. It also prevents larger configurations from using cross-partition communication. Signed-off-by: Robin Holt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/misc/sgi-xp/xpc_partition.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c index d551f09ccb79..6956f7e7d439 100644 --- a/drivers/misc/sgi-xp/xpc_partition.c +++ b/drivers/misc/sgi-xp/xpc_partition.c @@ -439,18 +439,23 @@ xpc_discovery(void) * nodes that can comprise an access protection grouping. The access * protection is in regards to memory, IOI and IPI. */ - max_regions = 64; region_size = xp_region_size; - switch (region_size) { - case 128: - max_regions *= 2; - case 64: - max_regions *= 2; - case 32: - max_regions *= 2; - region_size = 16; - DBUG_ON(!is_shub2()); + if (is_uv()) + max_regions = 256; + else { + max_regions = 64; + + switch (region_size) { + case 128: + max_regions *= 2; + case 64: + max_regions *= 2; + case 32: + max_regions *= 2; + region_size = 16; + DBUG_ON(!is_shub2()); + } } for (region = 0; region < max_regions; region++) { -- cgit v1.2.3 From 18f41f489a1ee1b296482d1b5bdf2ea4f8625cb6 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 8 Oct 2010 16:59:12 +0100 Subject: xen: ensure that all event channels start off bound to VCPU 0 commit b0097adeec27e30223c989561ab0f7aa60d1fe93 upstream. All event channels startbound to VCPU 0 so ensure that cpu_evtchn_mask is initialised to reflect this. Otherwise there is a race after registering an event channel but before the affinity is explicitly set where the event channel can be delivered. If this happens then the event channel remains pending in the L1 (evtchn_pending) array but is cleared in L2 (evtchn_pending_sel), this means the event channel cannot be reraised until another event channel happens to trigger the same L2 entry on that VCPU. sizeof(cpu_evtchn_mask(0))==sizeof(unsigned long*) which is not correct, and causes only the first 32 or 64 event channels (depending on architecture) to be initially bound to VCPU0. Use sizeof(struct cpu_evtchn_s) instead. Signed-off-by: Ian Campbell Cc: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/xen/events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 6830a4d067fc..076910891448 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -256,7 +256,7 @@ static void init_evtchn_cpu_bindings(void) } #endif - memset(cpu_evtchn_mask(0), ~0, sizeof(cpu_evtchn_mask(0))); + memset(cpu_evtchn_mask(0), ~0, sizeof(struct cpu_evtchn_s)); } static inline void clear_evtchn(int port) -- cgit v1.2.3 From 194587e5dfe26ffcf5358ee5c27dea79ff5e3d1d Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 29 Nov 2010 14:16:53 -0800 Subject: xen: don't bother to stop other cpus on shutdown/reboot commit 31e323cca9d5c8afd372976c35a5d46192f540d1 upstream. Xen will shoot all the VCPUs when we do a shutdown hypercall, so there's no need to do it manually. In any case it will fail because all the IPI irqs have been pulled down by this point, so the cross-CPU calls will simply hang forever. Until change 76fac077db6b34e2c6383a7b4f3f4f7b7d06d8ce the function calls were not synchronously waited for, so this wasn't apparent. However after that change the calls became synchronous leading to a hang on shutdown on multi-VCPU guests. Signed-off-by: Jeremy Fitzhardinge Cc: Alok Kataria Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/xen/enlighten.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 4d32089d093b..25d787c17ad8 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1000,10 +1000,6 @@ static void xen_reboot(int reason) { struct sched_shutdown r = { .reason = reason }; -#ifdef CONFIG_SMP - stop_other_cpus(); -#endif - if (HYPERVISOR_sched_op(SCHEDOP_shutdown, &r)) BUG(); } -- cgit v1.2.3 From 154893c8527b3eba012328c43736dfb918627edb Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 27 Oct 2010 15:34:17 -0700 Subject: ipc: initialize structure memory to zero for compat functions commit 03145beb455cf5c20a761e8451e30b8a74ba58d9 upstream. This takes care of leaking uninitialized kernel stack memory to userspace from non-zeroed fields in structs in compat ipc functions. Signed-off-by: Dan Rosenberg Cc: Manfred Spraul Cc: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- ipc/compat.c | 6 ++++++ ipc/compat_mq.c | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/ipc/compat.c b/ipc/compat.c index 9dc2c7d3c9e6..845a28738d3a 100644 --- a/ipc/compat.c +++ b/ipc/compat.c @@ -241,6 +241,8 @@ long compat_sys_semctl(int first, int second, int third, void __user *uptr) struct semid64_ds __user *up64; int version = compat_ipc_parse_version(&third); + memset(&s64, 0, sizeof(s64)); + if (!uptr) return -EINVAL; if (get_user(pad, (u32 __user *) uptr)) @@ -421,6 +423,8 @@ long compat_sys_msgctl(int first, int second, void __user *uptr) int version = compat_ipc_parse_version(&second); void __user *p; + memset(&m64, 0, sizeof(m64)); + switch (second & (~IPC_64)) { case IPC_INFO: case IPC_RMID: @@ -594,6 +598,8 @@ long compat_sys_shmctl(int first, int second, void __user *uptr) int err, err2; int version = compat_ipc_parse_version(&second); + memset(&s64, 0, sizeof(s64)); + switch (second & (~IPC_64)) { case IPC_RMID: case SHM_LOCK: diff --git a/ipc/compat_mq.c b/ipc/compat_mq.c index d8d1e9ff4e88..380ea4fe08e7 100644 --- a/ipc/compat_mq.c +++ b/ipc/compat_mq.c @@ -53,6 +53,9 @@ asmlinkage long compat_sys_mq_open(const char __user *u_name, void __user *p = NULL; if (u_attr && oflag & O_CREAT) { struct mq_attr attr; + + memset(&attr, 0, sizeof(attr)); + p = compat_alloc_user_space(sizeof(attr)); if (get_compat_mq_attr(&attr, u_attr) || copy_to_user(p, &attr, sizeof(attr))) @@ -127,6 +130,8 @@ asmlinkage long compat_sys_mq_getsetattr(mqd_t mqdes, struct mq_attr __user *p = compat_alloc_user_space(2 * sizeof(*p)); long ret; + memset(&mqstat, 0, sizeof(mqstat)); + if (u_mqstat) { if (get_compat_mq_attr(&mqstat, u_mqstat) || copy_to_user(p, &mqstat, sizeof(mqstat))) -- cgit v1.2.3 From e4b338bfb1e607111ab7b56cb6d497b08567c7e3 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Sat, 30 Oct 2010 18:22:49 +0400 Subject: ipc: shm: fix information leak to userland commit 3af54c9bd9e6f14f896aac1bb0e8405ae0bc7a44 upstream. The shmid_ds structure is copied to userland with shm_unused{,2,3} fields unitialized. It leads to leaking of contents of kernel stack memory. Signed-off-by: Vasiliy Kulikov Acked-by: Al Viro Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- ipc/shm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ipc/shm.c b/ipc/shm.c index 52ed77eb9713..b42738067146 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -473,6 +473,7 @@ static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_ { struct shmid_ds out; + memset(&out, 0, sizeof(out)); ipc64_perm_to_ipc_perm(&in->shm_perm, &out.shm_perm); out.shm_segsz = in->shm_segsz; out.shm_atime = in->shm_atime; -- cgit v1.2.3 From c1266e14138f7a0dc54c5db9a64556a57bbf52a8 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 22 Oct 2010 04:38:26 +0000 Subject: net: NETIF_F_HW_CSUM does not imply FCoE CRC offload commit 66c68bcc489fadd4f5e8839e966e3a366e50d1d5 upstream. NETIF_F_HW_CSUM indicates the ability to update an TCP/IP-style 16-bit checksum with the checksum of an arbitrary part of the packet data, whereas the FCoE CRC is something entirely different. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/core/dev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index a7054e88eb67..d7d352ba56cd 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1653,10 +1653,10 @@ EXPORT_SYMBOL(netif_device_attach); static bool can_checksum_protocol(unsigned long features, __be16 protocol) { - return ((features & NETIF_F_GEN_CSUM) || - ((features & NETIF_F_IP_CSUM) && + return ((features & NETIF_F_NO_CSUM) || + ((features & NETIF_F_V4_CSUM) && protocol == htons(ETH_P_IP)) || - ((features & NETIF_F_IPV6_CSUM) && + ((features & NETIF_F_V6_CSUM) && protocol == htons(ETH_P_IPV6)) || ((features & NETIF_F_FCOE_CRC) && protocol == htons(ETH_P_FCOE))); -- cgit v1.2.3 From 75f98b7f0ecca1f82d3a3bd44b8fbda04e949096 Mon Sep 17 00:00:00 2001 From: Graham Gower Date: Wed, 27 Oct 2010 15:33:00 -0700 Subject: drivers/char/vt_ioctl.c: fix VT_OPENQRY error value commit 1e0ad2881d50becaeea70ec696a80afeadf944d2 upstream. When all VT's are in use, VT_OPENQRY casts -1 to unsigned char before returning it to userspace as an int. VT255 is not the next available console. Signed-off-by: Graham Gower Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/char/vt_ioctl.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index cb19dbc52136..85cf2309a083 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -503,6 +503,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, struct kbd_struct * kbd; unsigned int console; unsigned char ucval; + unsigned int uival; void __user *up = (void __user *)arg; int i, perm; int ret = 0; @@ -657,7 +658,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, break; case KDGETMODE: - ucval = vc->vc_mode; + uival = vc->vc_mode; goto setint; case KDMAPDISP: @@ -695,7 +696,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, break; case KDGKBMODE: - ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW : + uival = ((kbd->kbdmode == VC_RAW) ? K_RAW : (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW : (kbd->kbdmode == VC_UNICODE) ? K_UNICODE : K_XLATE); @@ -717,9 +718,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, break; case KDGKBMETA: - ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT); + uival = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT); setint: - ret = put_user(ucval, (int __user *)arg); + ret = put_user(uival, (int __user *)arg); break; case KDGETKEYCODE: @@ -949,7 +950,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, for (i = 0; i < MAX_NR_CONSOLES; ++i) if (! VT_IS_IN_USE(i)) break; - ucval = i < MAX_NR_CONSOLES ? (i+1) : -1; + uival = i < MAX_NR_CONSOLES ? (i+1) : -1; goto setint; /* -- cgit v1.2.3 From 4ca06cb31057d86ed3d5ae54fdd99d15d5dc7811 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Wed, 22 Sep 2010 02:33:52 +0000 Subject: viafb: use proper register for colour when doing fill ops commit efd4f6398dc92b5bf392670df862f42a19f34cf2 upstream. The colour was written to a wrong register for fillrect operations. This sometimes caused empty console space (for example after 'clear') to have a different colour than desired. Fix this by writing to the correct register. Many thanks to Daniel Drake and Jon Nettleton for pointing out this issue and pointing me in the right direction for the fix. Fixes http://dev.laptop.org/ticket/9323 Signed-off-by: Florian Tobias Schandinat Cc: Joseph Chan Cc: Daniel Drake Cc: Jon Nettleton Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/video/via/accel.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index e44893ea590d..c2f4e6e166f1 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c @@ -283,11 +283,12 @@ static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height, writel(tmp, engine + 0x1C); } - if (op != VIA_BITBLT_COLOR) + if (op == VIA_BITBLT_FILL) { + writel(fg_color, engine + 0x58); + } else if (op == VIA_BITBLT_MONO) { writel(fg_color, engine + 0x4C); - - if (op == VIA_BITBLT_MONO) writel(bg_color, engine + 0x50); + } if (op == VIA_BITBLT_FILL) ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001; -- cgit v1.2.3 From 65f23ae22dc7bb397c35aa4453f755b6cd270c3e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 19 Nov 2010 15:29:19 +0100 Subject: sata_via: apply magic FIFO fix to vt6420 too commit b1353e4f40f6179ab26a3bb1b2e1fe29ffe534f5 upstream. vt6420 has the same FIFO overflow problem as vt6421 when combined with certain devices. This patch applies the magic fix to vt6420 too. Signed-off-by: Tejun Heo Reported-by: Martin Qvist Reported-by: Peter Zijlstra Cc: Joseph Chan Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/ata/sata_via.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 4730c42a5ee5..c51b8d25cfa8 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -538,7 +538,7 @@ static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) return 0; } -static void svia_configure(struct pci_dev *pdev) +static void svia_configure(struct pci_dev *pdev, int board_id) { u8 tmp8; @@ -577,7 +577,7 @@ static void svia_configure(struct pci_dev *pdev) } /* - * vt6421 has problems talking to some drives. The following + * vt6420/1 has problems talking to some drives. The following * is the fix from Joseph Chan . * * When host issues HOLD, device may send up to 20DW of data @@ -596,8 +596,9 @@ static void svia_configure(struct pci_dev *pdev) * * https://bugzilla.kernel.org/show_bug.cgi?id=15173 * http://article.gmane.org/gmane.linux.ide/46352 + * http://thread.gmane.org/gmane.linux.kernel/1062139 */ - if (pdev->device == 0x3249) { + if (board_id == vt6420 || board_id == vt6421) { pci_read_config_byte(pdev, 0x52, &tmp8); tmp8 |= 1 << 2; pci_write_config_byte(pdev, 0x52, tmp8); @@ -652,7 +653,7 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) return rc; - svia_configure(pdev); + svia_configure(pdev, board_id); pci_set_master(pdev); return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt, -- cgit v1.2.3 From 9b0d3ea667b7988bc29b4a7af9ba6b05c43bcb2b Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Thu, 23 Sep 2010 02:35:04 -0500 Subject: eCryptfs: Clear LOOKUP_OPEN flag when creating lower file commit 2e21b3f124eceb6ab5a07c8a061adce14ac94e14 upstream. eCryptfs was passing the LOOKUP_OPEN flag through to the lower file system, even though ecryptfs_create() doesn't support the flag. A valid filp for the lower filesystem could be returned in the nameidata if the lower file system's create() function supported LOOKUP_OPEN, possibly resulting in unencrypted writes to the lower file. However, this is only a potential problem in filesystems (FUSE, NFS, CIFS, CEPH, 9p) that eCryptfs isn't known to support today. https://bugs.launchpad.net/ecryptfs/+bug/641703 Reported-by: Kevin Buhr Signed-off-by: Tyler Hicks Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ecryptfs/inode.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 8cd617b66baa..6e1953fb4e07 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -70,15 +70,19 @@ ecryptfs_create_underlying_file(struct inode *lower_dir_inode, struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); struct dentry *dentry_save; struct vfsmount *vfsmount_save; + unsigned int flags_save; int rc; dentry_save = nd->path.dentry; vfsmount_save = nd->path.mnt; + flags_save = nd->flags; nd->path.dentry = lower_dentry; nd->path.mnt = lower_mnt; + nd->flags &= ~LOOKUP_OPEN; rc = vfs_create(lower_dir_inode, lower_dentry, mode, nd); nd->path.dentry = dentry_save; nd->path.mnt = vfsmount_save; + nd->flags = flags_save; return rc; } -- cgit v1.2.3 From 089cffe1b45748a81ce22c777a56406d43fe0c93 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Tue, 5 Oct 2010 18:53:45 +0200 Subject: ecryptfs: call vfs_setxattr() in ecryptfs_setxattr() commit 48b512e6857139393cdfce26348c362b87537018 upstream. Ecryptfs is a stackable filesystem which relies on lower filesystems the ability of setting/getting extended attributes. If there is a security module enabled on the system it updates the 'security' field of inodes according to the owned extended attribute set with the function vfs_setxattr(). When this function is performed on a ecryptfs filesystem the 'security' field is not updated for the lower filesystem since the call security_inode_post_setxattr() is missing for the lower inode. Further, the call security_inode_setxattr() is missing for the lower inode, leading to policy violations in the security module because specific checks for this hook are not performed (i. e. filesystem 'associate' permission on SELinux is not checked for the lower filesystem). This patch replaces the call of the setxattr() method of the lower inode in the function ecryptfs_setxattr() with vfs_setxattr(). Signed-off-by: Roberto Sassu Cc: Dustin Kirkland Acked-by: James Morris Signed-off-by: Tyler Hicks Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ecryptfs/inode.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 6e1953fb4e07..db9feb54d273 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "ecryptfs_kernel.h" @@ -1020,10 +1021,8 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, rc = -EOPNOTSUPP; goto out; } - mutex_lock(&lower_dentry->d_inode->i_mutex); - rc = lower_dentry->d_inode->i_op->setxattr(lower_dentry, name, value, - size, flags); - mutex_unlock(&lower_dentry->d_inode->i_mutex); + + rc = vfs_setxattr(lower_dentry, name, value, size, flags); out: return rc; } -- cgit v1.2.3 From 289f4fb78983150dcea9c06c2d8a4257d8032d49 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 24 Nov 2010 16:39:46 +1100 Subject: md/raid1: really fix recovery looping when single good device fails. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 8f9e0ee38f75d4740daa9e42c8af628d33d19a02 upstream. Commit 4044ba58dd15cb01797c4fd034f39ef4a75f7cc3 supposedly fixed a problem where if a raid1 with just one good device gets a read-error during recovery, the recovery would abort and immediately restart in an infinite loop. However it depended on raid1_remove_disk removing the spare device from the array. But that does not happen in this case. So add a test so that in the 'recovery_disabled' case, the device will be removed. This suitable for any kernel since 2.6.29 which is when recovery_disabled was introduced. Reported-by: Sebastian Färber Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/md/raid1.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index a948da8012de..2e99c29164d6 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1208,6 +1208,7 @@ static int raid1_remove_disk(mddev_t *mddev, int number) * is not possible. */ if (!test_bit(Faulty, &rdev->flags) && + !mddev->recovery_disabled && mddev->degraded < conf->raid_disks) { err = -EBUSY; goto abort; -- cgit v1.2.3 From 7f202301f48423a1327b5a4965d5d3955a7e960f Mon Sep 17 00:00:00 2001 From: Justin Maggard Date: Wed, 24 Nov 2010 16:36:17 +1100 Subject: md: fix return value of rdev_size_change() commit c26a44ed1e552aaa1d4ceb71842002d235fe98d7 upstream. When trying to grow an array by enlarging component devices, rdev_size_store() expects the return value of rdev_size_change() to be in sectors, but the actual value is returned in KBs. This functionality was broken by commit dd8ac336c13fd8afdb082ebacb1cddd5cf727889 so this patch is suitable for any kernel since 2.6.30. Signed-off-by: Justin Maggard Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/md/md.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 7476d959090f..7de96c2c68ac 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1278,7 +1278,7 @@ super_90_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors) md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size, rdev->sb_page); md_super_wait(rdev->mddev); - return num_sectors / 2; /* kB for sysfs */ + return num_sectors; } @@ -1644,7 +1644,7 @@ super_1_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors) md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size, rdev->sb_page); md_super_wait(rdev->mddev); - return num_sectors / 2; /* kB for sysfs */ + return num_sectors; } static struct super_type super_types[] = { -- cgit v1.2.3 From 67de320f9b82cad2dec335b3d523eada5a337b91 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Sat, 27 Nov 2010 13:58:04 -0500 Subject: ALSA: hda: Use BIOS auto-parsing instead of existing model quirk for MEDION MD2 commit ac70eb1305d5a81efd1e32327d7e79be15a63a5a upstream. BugLink: https://launchpad.net/bugs/682199 A 2.6.35 (Ubuntu Maverick) user, burningphantom1, reported a regression in audio: playback was inaudible through both speakers and headphones. In commit 272a527c04 of sound-2.6.git, a new model was added with this machine's PCI SSID. Fortunately, it is now sufficient to use the auto model for BIOS auto-parsing instead of the existing quirk. Playback, capture, and jack sense were verified working for both 2.6.35 and the alsa-driver snapshot from 2010-11-27 when model=auto is used. Reported-and-tested-by: burningphantom1 Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_realtek.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 76c4968c2a38..36a6639feef3 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9472,7 +9472,6 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763), SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763), SND_PCI_QUIRK(0x17aa, 0x101d, "Lenovo Sky", ALC888_LENOVO_SKY), - SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2), SND_PCI_QUIRK(0x17c0, 0x4085, "MEDION MD96630", ALC888_LENOVO_MS7195_DIG), SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66), -- cgit v1.2.3 From e14e0aafc584d46b128301bcf399f2dd6e6d2cc7 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 8 Nov 2010 19:01:47 +0100 Subject: tty: prevent DOS in the flush_to_ldisc commit e045fec48970df84647a47930fcf7a22ff7229c0 upstream. There's a small window inside the flush_to_ldisc function, where the tty is unlocked and calling ldisc's receive_buf function. If in this window new buffer is added to the tty, the processing might never leave the flush_to_ldisc function. This scenario will hog the cpu, causing other tty processing starving, and making it impossible to interface the computer via tty. I was able to exploit this via pty interface by sending only control characters to the master input, causing the flush_to_ldisc to be scheduled, but never actually generate any output. To reproduce, please run multiple instances of following code. - SNIP #define _XOPEN_SOURCE #include #include #include #include #include int main(int argc, char **argv) { int i, slave, master = getpt(); char buf[8192]; sprintf(buf, "%s", ptsname(master)); grantpt(master); unlockpt(master); slave = open(buf, O_RDWR); if (slave < 0) { perror("open slave failed"); return 1; } for(i = 0; i < sizeof(buf); i++) buf[i] = rand() % 32; while(1) { write(master, buf, sizeof(buf)); } return 0; } - SNIP The attached patch (based on -next tree) fixes this by checking on the tty buffer tail. Once it's reached, the current work is rescheduled and another could run. Signed-off-by: Jiri Olsa Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/char/tty_buffer.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c index cc1e9850d655..d8210ca00720 100644 --- a/drivers/char/tty_buffer.c +++ b/drivers/char/tty_buffer.c @@ -413,7 +413,8 @@ static void flush_to_ldisc(struct work_struct *work) spin_lock_irqsave(&tty->buf.lock, flags); if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) { - struct tty_buffer *head; + struct tty_buffer *head, *tail = tty->buf.tail; + int seen_tail = 0; while ((head = tty->buf.head) != NULL) { int count; char *char_buf; @@ -423,6 +424,15 @@ static void flush_to_ldisc(struct work_struct *work) if (!count) { if (head->next == NULL) break; + /* + There's a possibility tty might get new buffer + added during the unlock window below. We could + end up spinning in here forever hogging the CPU + completely. To avoid this let's have a rest each + time we processed the tail buffer. + */ + if (tail == head) + seen_tail = 1; tty->buf.head = head->next; tty_buffer_free(tty, head); continue; @@ -432,7 +442,7 @@ static void flush_to_ldisc(struct work_struct *work) line discipline as we want to empty the queue */ if (test_bit(TTY_FLUSHPENDING, &tty->flags)) break; - if (!tty->receive_room) { + if (!tty->receive_room || seen_tail) { schedule_delayed_work(&tty->buf.work, 1); break; } -- cgit v1.2.3 From 7a4239f949215adc0f5271cb176c48aafbe9a71e Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sun, 31 Oct 2010 23:17:51 +0100 Subject: TTY: restore tty_ldisc_wait_idle commit 100eeae2c5ce23b4db93ff320ee330ef1d740151 upstream. It was removed in 65b770468e98 (tty-ldisc: turn ldisc user count into a proper refcount), but we need to wait for last user to quit the ldisc before we close it in tty_set_ldisc. Otherwise weird things start to happen. There might be processes waiting in tty_read->n_tty_read on tty->read_wait for input to appear and at that moment, a change of ldisc is fatal. n_tty_close is called, it frees read_buf and the waiting process is still in the middle of reading and goes nuts after it is woken. Previously we prevented close to happen when others are in ldisc ops by tty_ldisc_wait_idle in tty_set_ldisc. But the commit above removed that. So revoke the change and test whether there is 1 user (=we), and allow the close then. We can do that without ldisc/tty locks, because nobody else can open the device due to TTY_LDISC_CHANGING bit set, so we in fact wait for everybody to leave. I don't understand why tty_ldisc_lock would be needed either when the counter is an atomic variable, so this is a lockless tty_ldisc_wait_idle. On the other hand, if we fail to wait (timeout or signal), we have to reenable the halted ldiscs, so we take ldisc lock and reuse the setup path at the end of tty_set_ldisc. Signed-off-by: Jiri Slaby Acked-by: Linus Torvalds Tested-by: Sebastian Andrzej Siewior Signed-off-by: Andi Kleen LKML-Reference: <20101031104136.GA511@Chamillionaire.breakpoint.cc> LKML-Reference: <1287669539-22644-1-git-send-email-jslaby@suse.cz> Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/tty_ldisc.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index 500e740ec5e4..df5e7db40d13 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c @@ -47,6 +47,7 @@ static DEFINE_SPINLOCK(tty_ldisc_lock); static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); +static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_idle); /* Line disc dispatch table */ static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; @@ -83,6 +84,7 @@ static void put_ldisc(struct tty_ldisc *ld) return; } local_irq_restore(flags); + wake_up(&tty_ldisc_idle); } /** @@ -529,6 +531,23 @@ static int tty_ldisc_halt(struct tty_struct *tty) return cancel_delayed_work_sync(&tty->buf.work); } +/** + * tty_ldisc_wait_idle - wait for the ldisc to become idle + * @tty: tty to wait for + * + * Wait for the line discipline to become idle. The discipline must + * have been halted for this to guarantee it remains idle. + */ +static int tty_ldisc_wait_idle(struct tty_struct *tty) +{ + int ret; + ret = wait_event_interruptible_timeout(tty_ldisc_idle, + atomic_read(&tty->ldisc->users) == 1, 5 * HZ); + if (ret < 0) + return ret; + return ret > 0 ? 0 : -EBUSY; +} + /** * tty_set_ldisc - set line discipline * @tty: the terminal to set @@ -632,8 +651,17 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) flush_scheduled_work(); + retval = tty_ldisc_wait_idle(tty); + mutex_lock(&tty->ldisc_mutex); lock_kernel(); + + /* handle wait idle failure locked */ + if (retval) { + tty_ldisc_put(new_ldisc); + goto enable; + } + if (test_bit(TTY_HUPPED, &tty->flags)) { /* We were raced by the hangup method. It will have stomped the ldisc data and closed the ldisc down */ @@ -667,6 +695,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) tty_ldisc_put(o_ldisc); +enable: /* * Allow ldisc referencing to occur again */ -- cgit v1.2.3 From d509e248785859c7cd3d5b6947b92c6b1159f075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20R=C3=A9tornaz?= Date: Wed, 27 Oct 2010 17:13:21 +0200 Subject: tty_ldisc: Fix BUG() on hangup commit 1c95ba1e1de7edffc0c4e275e147f1a9eb1f81ae upstream. A kernel BUG when bluetooth rfcomm connection drop while the associated serial port is open is sometime triggered. It seems that the line discipline can disappear between the tty_ldisc_put and tty_ldisc_get. This patch fall back to the N_TTY line discipline if the previous discipline is not available anymore. Signed-off-by: Philippe Retornaz Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/char/tty_ldisc.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index df5e7db40d13..7af1a1563e8f 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c @@ -741,9 +741,12 @@ static void tty_reset_termios(struct tty_struct *tty) * state closed */ -static void tty_ldisc_reinit(struct tty_struct *tty, int ldisc) +static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) { - struct tty_ldisc *ld; + struct tty_ldisc *ld = tty_ldisc_get(ldisc); + + if (IS_ERR(ld)) + return -1; tty_ldisc_close(tty, tty->ldisc); tty_ldisc_put(tty->ldisc); @@ -751,10 +754,10 @@ static void tty_ldisc_reinit(struct tty_struct *tty, int ldisc) /* * Switch the line discipline back */ - ld = tty_ldisc_get(ldisc); - BUG_ON(IS_ERR(ld)); tty_ldisc_assign(tty, ld); tty_set_termios_ldisc(tty, ldisc); + + return 0; } /** @@ -816,13 +819,16 @@ void tty_ldisc_hangup(struct tty_struct *tty) a FIXME */ if (tty->ldisc) { /* Not yet closed */ if (reset == 0) { - tty_ldisc_reinit(tty, tty->termios->c_line); - err = tty_ldisc_open(tty, tty->ldisc); + + if (!tty_ldisc_reinit(tty, tty->termios->c_line)) + err = tty_ldisc_open(tty, tty->ldisc); + else + err = 1; } /* If the re-open fails or we reset then go to N_TTY. The N_TTY open cannot fail */ if (reset || err) { - tty_ldisc_reinit(tty, N_TTY); + BUG_ON(tty_ldisc_reinit(tty, N_TTY)); WARN_ON(tty_ldisc_open(tty, tty->ldisc)); } tty_ldisc_enable(tty); -- cgit v1.2.3 From 89f26850f00bc19c52e62e47802e7088cb87f946 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 25 Nov 2010 00:27:54 +0100 Subject: TTY: ldisc, fix open flag handling commit 7f90cfc505d613f4faf096e0d84ffe99208057d9 upstream. When a concrete ldisc open fails in tty_ldisc_open, we forget to clear TTY_LDISC_OPEN. This causes a false warning on the next ldisc open: WARNING: at drivers/char/tty_ldisc.c:445 tty_ldisc_open+0x26/0x38() Hardware name: System Product Name Modules linked in: ... Pid: 5251, comm: a.out Tainted: G W 2.6.32-5-686 #1 Call Trace: [] ? warn_slowpath_common+0x5e/0x8a [] ? warn_slowpath_null+0xa/0xc [] ? tty_ldisc_open+0x26/0x38 [] ? tty_set_ldisc+0x218/0x304 ... So clear the bit when failing... Introduced in c65c9bc3efa (tty: rewrite the ldisc locking) back in 2.6.31-rc1. Signed-off-by: Jiri Slaby Cc: Alan Cox Reported-by: Sergey Lapin Tested-by: Sergey Lapin Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/char/tty_ldisc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index 7af1a1563e8f..236628f3fea1 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c @@ -452,6 +452,8 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) /* BKL here locks verus a hangup event */ lock_kernel(); ret = ld->ops->open(tty); + if (ret) + clear_bit(TTY_LDISC_OPEN, &tty->flags); unlock_kernel(); return ret; } -- cgit v1.2.3 From 593c62f0ef892aaa5045805933d139125f9614ba Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Mon, 1 Nov 2010 07:11:54 -0700 Subject: usbnet: fix usb_autopm_get_interface failure(v1) commit b0786b430c982dffbb44d8030e6b6088671ce745 upstream. Since usbnet already took usb runtime pm, we have to enable runtime pm for usb interface of usbnet, otherwise usb_autopm_get_interface may return failure and cause 'ifconfig usb0 up' failed if USB_SUSPEND(RUNTIME_PM) is enabled. Cc: David Brownell Cc: "David S. Miller" Cc: Ben Hutchings Cc: Joe Perches Cc: Oliver Neukum Cc: Andy Shevchenko Signed-off-by: Ming Lei Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/usb/usbnet.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 81c76ada8e56..2793cff5ddbb 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -44,6 +44,7 @@ #include #include #include +#include #define DRIVER_VERSION "22-Aug-2005" @@ -1272,6 +1273,16 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) struct usb_device *xdev; int status; const char *name; + struct usb_driver *driver = to_usb_driver(udev->dev.driver); + + /* usbnet already took usb runtime pm, so have to enable the feature + * for usb interface, otherwise usb_autopm_get_interface may return + * failure if USB_SUSPEND(RUNTIME_PM) is enabled. + */ + if (!driver->supports_autosuspend) { + driver->supports_autosuspend = 1; + pm_runtime_enable(&udev->dev); + } name = udev->dev.driver->name; info = (struct driver_info *) prod->driver_info; -- cgit v1.2.3 From 4164f74d5f4ab153965b797920e87cdc3991febe Mon Sep 17 00:00:00 2001 From: Philipp Merkel Date: Fri, 1 Oct 2010 15:38:59 +0200 Subject: HID: Fix for problems with eGalax/DWAV multi-touch-screen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f51661105c3c8a0afcd69f995a4f4a10e53da153 upstream. This patch fixes three problems with the eGalax/DWAV multi-touch screen found in the Eee PC T101MT: 1) While there is a dedicated multitouch driver for the screen (hid-egalax.c), the MULTI_INPUT quirk is also applied, preventing the hid-egalax driver from working. This patch removes the quirk so the hid-egalax driver can handle the device correctly. 2) The x and y coordinates sent by the screen in multi-touch mode are shifted by three bits from the events sent in single-touch mode, thus the coordinates are out of range, leading to the pointer being stuck in the bottom-right corner if no additional calibration is applied (e.g. in the X evdev driver). This patch shifts the coordinates back. This does not decrease accuracy as the last three bits of the "wrong" coordinates are always 0. 3) Only multi-touch pressure events are sent, single touch emulation is missing pressure information. This patch adds single-touch ABS_PRESSURE events. Signed-off-by: Philipp Merkel Acked-by: Stéphane Chatty Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/hid/hid-egalax.c | 16 +++++++++++----- drivers/hid/usbhid/hid-quirks.c | 1 - 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/hid/hid-egalax.c b/drivers/hid/hid-egalax.c index f44bdc084cb2..5cd004ef57a5 100644 --- a/drivers/hid/hid-egalax.c +++ b/drivers/hid/hid-egalax.c @@ -31,7 +31,7 @@ struct egalax_data { bool first; /* is this the first finger in the frame? */ bool valid; /* valid finger data, or just placeholder? */ bool activity; /* at least one active finger previously? */ - __u16 lastx, lasty; /* latest valid (x, y) in the frame */ + __u16 lastx, lasty, lastz; /* latest valid (x, y, z) in the frame */ }; static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi, @@ -79,6 +79,10 @@ static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi, case HID_DG_TIPPRESSURE: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_PRESSURE); + /* touchscreen emulation */ + input_set_abs_params(hi->input, ABS_PRESSURE, + field->logical_minimum, + field->logical_maximum, 0, 0); return 1; } return 0; @@ -109,8 +113,8 @@ static void egalax_filter_event(struct egalax_data *td, struct input_dev *input) if (td->valid) { /* emit multitouch events */ input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); - input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); - input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); + input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x >> 3); + input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y >> 3); input_event(input, EV_ABS, ABS_MT_PRESSURE, td->z); input_mt_sync(input); @@ -121,6 +125,7 @@ static void egalax_filter_event(struct egalax_data *td, struct input_dev *input) */ td->lastx = td->x; td->lasty = td->y; + td->lastz = td->z; } /* @@ -129,8 +134,9 @@ static void egalax_filter_event(struct egalax_data *td, struct input_dev *input) * the oldest on the panel, the one we want for single touch */ if (!td->first && td->activity) { - input_event(input, EV_ABS, ABS_X, td->lastx); - input_event(input, EV_ABS, ABS_Y, td->lasty); + input_event(input, EV_ABS, ABS_X, td->lastx >> 3); + input_event(input, EV_ABS, ABS_Y, td->lasty >> 3); + input_event(input, EV_ABS, ABS_PRESSURE, td->lastz); } if (!td->valid) { diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 5f5aa39b3988..3fe54901edd8 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -33,7 +33,6 @@ static const struct hid_blacklist { { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, -- cgit v1.2.3 From d4a57ec4ecb5e724ee1a2178eff81669562f6da7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Thu, 21 Oct 2010 04:05:15 -0300 Subject: gspca - sonixj: Fix a regression of sensors hv7131r and mi0360 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 0303a90a744662e934877a5d637a43197229274b upstream. The bug was introduced by commit 23a98274cc348880ecb6803307c254448084953a applying values of sensor sp80708 to sensors hv7131r and mi0360. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/media/video/gspca/sonixj.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 176c5b3d5e6f..d5754c1506f1 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -2488,8 +2488,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg1 = 0x44; reg17 = 0xa2; break; - default: -/* case SENSOR_SP80708: */ + case SENSOR_SP80708: init = sp80708_sensor_param1; if (mode) { /*?? reg1 = 0x04; * 320 clk 48Mhz */ -- cgit v1.2.3 From d00181bad9f23e62ce22503876e7a29b5424e7ed Mon Sep 17 00:00:00 2001 From: James M McLaren Date: Sun, 3 Oct 2010 19:09:18 -0300 Subject: hdpvr: Add missing URB_NO_TRANSFER_DMA_MAP flag commit 4f5c933abb34532dc962185c999509b97a97fa1b upstream. Necessary on arm. Signed-off-by: Janne Grunau Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/media/video/hdpvr/hdpvr-video.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index c338f3f62e77..9cccb74ab555 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c @@ -157,6 +157,7 @@ int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count) mem, dev->bulk_in_size, hdpvr_read_bulk_callback, buf); + buf->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; buf->status = BUFSTAT_AVAILABLE; list_add_tail(&buf->buff_list, &dev->free_buff_list); } -- cgit v1.2.3 From e945dc312ad16872c7094990fd390ec0c3b5a6a0 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 1 Oct 2010 18:13:41 -0300 Subject: drivers/media/video/cx23885/cx23885-core.c: fix cx23885_dev_checkrevision() commit abe1def46d84aa27d3f84d729204b162e8c64d76 upstream. It was missing the `break'. Addresses https://bugzilla.kernel.org/show_bug.cgi?id=18672 Reported-by: Igor Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/media/video/cx23885/cx23885-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 0dde57e96d30..fb67433406e1 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -737,6 +737,7 @@ static void cx23885_dev_checkrevision(struct cx23885_dev *dev) case 0x0e: /* CX23887-15Z */ dev->hwrevision = 0xc0; + break; case 0x0f: /* CX23887-14Z */ dev->hwrevision = 0xb1; -- cgit v1.2.3 From e110ca176b8d6499d9b6d69a5e1b9055f10e6a1b Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 25 Oct 2010 03:21:24 +0200 Subject: KVM: Write protect memory after slot swap commit edde99ce05290e50ce0b3495d209e54e6349ab47 upstream. I have observed the following bug trigger: 1. userspace calls GET_DIRTY_LOG 2. kvm_mmu_slot_remove_write_access is called and makes a page ro 3. page fault happens and makes the page writeable fault is logged in the bitmap appropriately 4. kvm_vm_ioctl_get_dirty_log swaps slot pointers a lot of time passes 5. guest writes into the page 6. userspace calls GET_DIRTY_LOG At point (5), bitmap is clean and page is writeable, thus, guest modification of memory is not logged and GET_DIRTY_LOG returns an empty bitmap. The rule is that all pages are either dirty in the current bitmap, or write-protected, which is violated here. It seems that just moving kvm_mmu_slot_remove_write_access down to after the slot pointer swap should fix this bug. Signed-off-by: Michael S. Tsirkin Signed-off-by: Avi Kivity Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/kvm/x86.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index be9251193d2a..ff274a142ed8 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2825,10 +2825,6 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, if (is_dirty) { struct kvm_memslots *slots, *old_slots; - spin_lock(&kvm->mmu_lock); - kvm_mmu_slot_remove_write_access(kvm, log->slot); - spin_unlock(&kvm->mmu_lock); - slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL); if (!slots) goto out_free; @@ -2841,6 +2837,11 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, synchronize_srcu_expedited(&kvm->srcu); dirty_bitmap = old_slots->memslots[log->slot].dirty_bitmap; kfree(old_slots); + + spin_lock(&kvm->mmu_lock); + kvm_mmu_slot_remove_write_access(kvm, log->slot); + spin_unlock(&kvm->mmu_lock); + } r = 0; -- cgit v1.2.3 From be6eb177af13eceaef0052a0628b7153844bbea9 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Sat, 30 Oct 2010 22:54:47 +0400 Subject: KVM: x86: fix information leak to userland commit 97e69aa62f8b5d338d6cff49be09e37cc1262838 upstream. Structures kvm_vcpu_events, kvm_debugregs, kvm_pit_state2 and kvm_clock_data are copied to userland with some padding and reserved fields unitialized. It leads to leaking of contents of kernel stack memory. We have to initialize them to zero. In patch v1 Jan Kiszka suggested to fill reserved fields with zeros instead of memset'ting the whole struct. It makes sense as these fields are explicitly marked as padding. No more fields need zeroing. Signed-off-by: Vasiliy Kulikov Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/kvm/x86.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index ff274a142ed8..eee5cdd29bc2 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2220,6 +2220,7 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu, !kvm_exception_is_soft(vcpu->arch.exception.nr); events->exception.nr = vcpu->arch.exception.nr; events->exception.has_error_code = vcpu->arch.exception.has_error_code; + events->exception.pad = 0; events->exception.error_code = vcpu->arch.exception.error_code; events->interrupt.injected = @@ -2233,13 +2234,14 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu, events->nmi.injected = vcpu->arch.nmi_injected; events->nmi.pending = vcpu->arch.nmi_pending; events->nmi.masked = kvm_x86_ops->get_nmi_mask(vcpu); + events->nmi.pad = 0; events->sipi_vector = vcpu->arch.sipi_vector; events->flags = (KVM_VCPUEVENT_VALID_NMI_PENDING | KVM_VCPUEVENT_VALID_SIPI_VECTOR | KVM_VCPUEVENT_VALID_SHADOW); - + memset(&events->reserved, 0, sizeof(events->reserved)); vcpu_put(vcpu); } @@ -2289,6 +2291,7 @@ static void kvm_vcpu_ioctl_x86_get_debugregs(struct kvm_vcpu *vcpu, dbgregs->dr6 = vcpu->arch.dr6; dbgregs->dr7 = vcpu->arch.dr7; dbgregs->flags = 0; + memset(&dbgregs->reserved, 0, sizeof(dbgregs->reserved)); vcpu_put(vcpu); } @@ -2756,6 +2759,7 @@ static int kvm_vm_ioctl_get_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps) sizeof(ps->channels)); ps->flags = kvm->arch.vpit->pit_state.flags; mutex_unlock(&kvm->arch.vpit->pit_state.lock); + memset(&ps->reserved, 0, sizeof(ps->reserved)); return r; } @@ -3153,6 +3157,7 @@ long kvm_arch_vm_ioctl(struct file *filp, now_ns = timespec_to_ns(&now); user_ns.clock = kvm->arch.kvmclock_offset + now_ns; user_ns.flags = 0; + memset(&user_ns.pad, 0, sizeof(user_ns.pad)); r = -EFAULT; if (copy_to_user(argp, &user_ns, sizeof(user_ns))) -- cgit v1.2.3 From d3f813da18f83a31f2678988b450e6a1c94c95ed Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 19 Oct 2010 18:48:35 +0200 Subject: KVM: Correct ordering of ldt reload wrt fs/gs reload commit 0a77fe4c188e25917799f2356d4aa5e6d80c39a2 upstream. If fs or gs refer to the ldt, they must be reloaded after the ldt. Reorder the code to that effect. Userspace code that uses the ldt with kvm is nonexistent, so this doesn't fix a user-visible bug. Signed-off-by: Avi Kivity Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/kvm/svm.c | 2 +- arch/x86/kvm/vmx.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 02a5603695e3..9ca703219d72 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -3184,9 +3184,9 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp; vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip; + kvm_load_ldt(ldt_selector); kvm_load_fs(fs_selector); kvm_load_gs(gs_selector); - kvm_load_ldt(ldt_selector); load_host_msrs(vcpu); reload_tss(vcpu); diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 7d043883d9bc..39ac45694d51 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -791,8 +791,6 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) ++vmx->vcpu.stat.host_state_reload; vmx->host_state.loaded = 0; - if (vmx->host_state.fs_reload_needed) - kvm_load_fs(vmx->host_state.fs_sel); if (vmx->host_state.gs_ldt_reload_needed) { kvm_load_ldt(vmx->host_state.ldt_sel); /* @@ -806,6 +804,8 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) #endif local_irq_restore(flags); } + if (vmx->host_state.fs_reload_needed) + loadsegment(fs, vmx->host_state.fs_sel); reload_tss(); #ifdef CONFIG_X86_64 if (is_long_mode(&vmx->vcpu)) { -- cgit v1.2.3 From d46d45da0b45490b805f70e3d2e05dd7fbf58a23 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 29 Oct 2010 15:41:17 -0700 Subject: ASoC: Remove volatility from WM8900 POWER1 register commit 6d212d8e86fb4221bd91b9266b7567ee2b83bd01 upstream. Not all bits can be read back from POWER1 so avoid corruption when using a read/modify/write cycle by marking it non-volatile - the only thing we read back from it is the chip revision which has diagnostic value only. We can re-add later but that's a more invasive change than is suitable for a bugfix. Signed-off-by: Mark Brown Acked-by: Liam Girdwood Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/soc/codecs/wm8900.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 5da17a704e5a..4b8ffc2ea71d 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -188,7 +188,6 @@ static int wm8900_volatile_register(unsigned int reg) { switch (reg) { case WM8900_REG_ID: - case WM8900_REG_POWER1: return 1; default: return 0; @@ -1236,11 +1235,6 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, goto err; } - /* Read back from the chip */ - reg = snd_soc_read(codec, WM8900_REG_POWER1); - reg = (reg >> 12) & 0xf; - dev_info(&i2c->dev, "WM8900 revision %d\n", reg); - wm8900_reset(codec); /* Turn the chip on */ -- cgit v1.2.3 From 1a74f9cc24d9255e24e6001476ed5acb6448d49b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 24 Nov 2010 10:20:33 +0800 Subject: ASoC: wm8961 - clear WM8961_DACSLOPE bit for normal mode commit 08b1a38465cab8c2224a5202c7a3b5e5f5630894 upstream. DACSLOPE bit of Register 06h ADC and DAC Control 2: 0: Normal mode 1: Sloping stop-band mode Thus in the case of normal mode, we should clear DACSLOPE bit. Signed-off-by: Axel Lin Acked-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/soc/codecs/wm8961.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 5b9a756242f1..4cda28dceb0f 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -711,7 +711,7 @@ static int wm8961_hw_params(struct snd_pcm_substream *substream, if (fs <= 24000) reg |= WM8961_DACSLOPE; else - reg &= WM8961_DACSLOPE; + reg &= ~WM8961_DACSLOPE; snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg); return 0; -- cgit v1.2.3 From 4d21e4b72b282e24fdf6a1993ef21730df94fe86 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 24 Nov 2010 10:21:54 +0800 Subject: ASoC: wm8961 - clear WM8961_MCLKDIV bit for freq <= 16500000 commit 2f7dceeda4708f470fd927adb3861bd8ebbe2310 upstream. MCLKDIV bit of Register 04h Clocking1: 0 : Divide by 1 1 : Divide by 2 Thus in the case of freq <= 16500000, we should clear MCLKDIV bit. Signed-off-by: Axel Lin Acked-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/soc/codecs/wm8961.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 4cda28dceb0f..3499c78aab81 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -736,7 +736,7 @@ static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id, freq /= 2; } else { dev_dbg(codec->dev, "Using MCLK/1 for %dHz MCLK\n", freq); - reg &= WM8961_MCLKDIV; + reg &= ~WM8961_MCLKDIV; } snd_soc_write(codec, WM8961_CLOCKING1, reg); -- cgit v1.2.3 From 329ad1cf88c3007e095a304028d11021eae8d402 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 25 Oct 2010 11:41:53 +0200 Subject: firewire: ohci: fix buffer overflow in AR split packet handling commit 85f7ffd5d2b320f73912b15fe8cef34bae297daf upstream. When the controller had to split a received asynchronous packet into two buffers, the driver tries to reassemble it by copying both parts into the first page. However, if size + rest > PAGE_SIZE, i.e., if the yet unhandled packets before the split packet, the split packet itself, and any received packets after the split packet are together larger than one page, then the memory after the first page would get overwritten. To fix this, do not try to copy the data of all unhandled packets at once, but copy the possibly needed data every time when handling a packet. This gets rid of most of the infamous crashes and data corruptions when using firewire-net. Signed-off-by: Clemens Ladisch Tested-by: Maxim Levitsky Signed-off-by: Stefan Richter Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/firewire/ohci.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 4b521dd5a9d9..725bb3c272b0 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -684,7 +684,7 @@ static void ar_context_tasklet(unsigned long data) d = &ab->descriptor; if (d->res_count == 0) { - size_t size, rest, offset; + size_t size, size2, rest, pktsize, size3, offset; dma_addr_t start_bus; void *start; @@ -701,12 +701,41 @@ static void ar_context_tasklet(unsigned long data) ab = ab->next; d = &ab->descriptor; size = buffer + PAGE_SIZE - ctx->pointer; + /* valid buffer data in the next page */ rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count); + /* what actually fits in this page */ + size2 = min(rest, (size_t)PAGE_SIZE - size); memmove(buffer, ctx->pointer, size); - memcpy(buffer + size, ab->data, rest); + memcpy(buffer + size, ab->data, size2); ctx->current_buffer = ab; ctx->pointer = (void *) ab->data + rest; - end = buffer + size + rest; + + while (size > 0) { + void *next = handle_ar_packet(ctx, buffer); + pktsize = next - buffer; + if (pktsize >= size) { + /* + * We have handled all the data that was + * originally in this page, so we can now + * continue in the next page. + */ + buffer = next; + break; + } + /* move the next packet to the start of the buffer */ + memmove(buffer, next, size + size2 - pktsize); + size -= pktsize; + /* fill up this page again */ + size3 = min(rest - size2, + (size_t)PAGE_SIZE - size - size2); + memcpy(buffer + size + size2, + (void *) ab->data + size2, size3); + size2 += size3; + } + + /* handle the packets that are fully in the next page */ + buffer = (void *) ab->data + (buffer - (start + size)); + end = (void *) ab->data + rest; while (buffer < end) buffer = handle_ar_packet(ctx, buffer); -- cgit v1.2.3 From 48059b90318aff5a2578d5a1d10ea7ac76e03e18 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 25 Oct 2010 11:42:20 +0200 Subject: firewire: ohci: fix race in AR split packet handling commit a1f805e5e73a8fe166b71c6592d3837df0cd5e2e upstream. When handling an AR buffer that has been completely filled, we assumed that its descriptor will not be read by the controller and can be overwritten. However, when the last received packet happens to end at the end of the buffer, the controller might not yet have moved on to the next buffer and might read the branch address later. If we overwrite and free the page before that, the DMA context will either go dead because of an invalid Z value, or go off into some random memory. To fix this, ensure that the descriptor does not get overwritten by using only the actual buffer instead of the entire page for reassembling the split packet. Furthermore, to avoid freeing the page too early, move on to the next buffer only when some data in it guarantees that the controller has moved on. This should eliminate the remaining firewire-net problems. Signed-off-by: Clemens Ladisch Tested-by: Maxim Levitsky Signed-off-by: Stefan Richter Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/firewire/ohci.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 725bb3c272b0..0942efb8d443 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -695,20 +695,19 @@ static void ar_context_tasklet(unsigned long data) */ offset = offsetof(struct ar_buffer, data); - start = buffer = ab; + start = ab; start_bus = le32_to_cpu(ab->descriptor.data_address) - offset; + buffer = ab->data; ab = ab->next; d = &ab->descriptor; - size = buffer + PAGE_SIZE - ctx->pointer; + size = start + PAGE_SIZE - ctx->pointer; /* valid buffer data in the next page */ rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count); /* what actually fits in this page */ - size2 = min(rest, (size_t)PAGE_SIZE - size); + size2 = min(rest, (size_t)PAGE_SIZE - offset - size); memmove(buffer, ctx->pointer, size); memcpy(buffer + size, ab->data, size2); - ctx->current_buffer = ab; - ctx->pointer = (void *) ab->data + rest; while (size > 0) { void *next = handle_ar_packet(ctx, buffer); @@ -727,22 +726,30 @@ static void ar_context_tasklet(unsigned long data) size -= pktsize; /* fill up this page again */ size3 = min(rest - size2, - (size_t)PAGE_SIZE - size - size2); + (size_t)PAGE_SIZE - offset - size - size2); memcpy(buffer + size + size2, (void *) ab->data + size2, size3); size2 += size3; } - /* handle the packets that are fully in the next page */ - buffer = (void *) ab->data + (buffer - (start + size)); - end = (void *) ab->data + rest; + if (rest > 0) { + /* handle the packets that are fully in the next page */ + buffer = (void *) ab->data + + (buffer - (start + offset + size)); + end = (void *) ab->data + rest; - while (buffer < end) - buffer = handle_ar_packet(ctx, buffer); + while (buffer < end) + buffer = handle_ar_packet(ctx, buffer); - dma_free_coherent(ohci->card.device, PAGE_SIZE, - start, start_bus); - ar_context_add_page(ctx); + ctx->current_buffer = ab; + ctx->pointer = end; + + dma_free_coherent(ohci->card.device, PAGE_SIZE, + start, start_bus); + ar_context_add_page(ctx); + } else { + ctx->pointer = start + PAGE_SIZE; + } } else { buffer = ctx->pointer; ctx->pointer = end = -- cgit v1.2.3 From 0e2009a0ee6bc00043d66713e6649820042241a8 Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Mon, 22 Nov 2010 10:59:36 +0100 Subject: ALSA: hda - Fixed ALC887-VD initial error commit 01e0f1378c47947b825eac05c98697ab1be1c86f upstream. ALC887-VD is like ALC888-VD. It can not be initialized as ALC882. Signed-off-by: Kailang Yang Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_realtek.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 36a6639feef3..a4f85b4b2259 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -18783,7 +18783,10 @@ static int patch_alc888(struct hda_codec *codec) { if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){ kfree(codec->chip_name); - codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL); + if (codec->vendor_id == 0x10ec0887) + codec->chip_name = kstrdup("ALC887-VD", GFP_KERNEL); + else + codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL); if (!codec->chip_name) { alc_free(codec); return -ENOMEM; @@ -18825,7 +18828,7 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A", .patch = patch_alc882 }, { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 }, - { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc882 }, + { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc888 }, { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200", .patch = patch_alc882 }, { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 }, -- cgit v1.2.3 From 18a9c40e9cbbde72235f911c07d9319a12db19f4 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Mon, 1 Nov 2010 01:14:51 -0400 Subject: ALSA: ac97: Apply quirk for Dell Latitude D610 binding Master and Headphone controls commit 0613a59456980161d0cd468bae6c63d772743102 upstream. BugLink: https://launchpad.net/bugs/669279 The original reporter states: "The Master mixer does not change the volume from the headphone output (which is affected by the headphone mixer). Instead it only seems to control the on-board speaker volume. This confuses PulseAudio greatly as the Master channel is merged into the volume mix." Fix this symptom by applying the hp_only quirk for the reporter's SSID. The fix is applicable to all stable kernels. Reported-and-tested-by: Ben Gamari Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/intel8x0.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 467749249576..ebfa1f8b70c1 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -1864,6 +1864,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "Dell Inspiron 8600", /* STAC9750/51 */ .type = AC97_TUNE_HP_ONLY }, + { + .subvendor = 0x1028, + .subdevice = 0x0182, + .name = "Dell Latitude D610", /* STAC9750/51 */ + .type = AC97_TUNE_HP_ONLY + }, { .subvendor = 0x1028, .subdevice = 0x0186, -- cgit v1.2.3 From a5bbcf1a635c40898cf3e5209f03710df588187c Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Thu, 9 Sep 2010 08:51:44 +0200 Subject: ALSA: HDA: Add fixup pins for Ideapad Y550 commit 6cb3b707f95954ac18f19b4b3919af235738371a upstream. By adding the subwoofer as a speaker pin, it is treated correctly when auto-muting. BugLink: https://launchpad.net/bugs/611803 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_realtek.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a4f85b4b2259..26820cd0ea98 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -18679,6 +18679,26 @@ static void alc662_auto_init(struct hda_codec *codec) alc_inithook(codec); } +enum { + ALC662_FIXUP_IDEAPAD, +}; + +static const struct alc_fixup alc662_fixups[] = { + [ALC662_FIXUP_IDEAPAD] = { + .pins = (const struct alc_pincfg[]) { + { 0x17, 0x99130112 }, /* subwoofer */ + { } + } + }, +}; + +static struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), + {} +}; + + + static int patch_alc662(struct hda_codec *codec) { struct alc_spec *spec; @@ -18711,6 +18731,7 @@ static int patch_alc662(struct hda_codec *codec) } if (board_config == ALC662_AUTO) { + alc_pick_fixup(codec, alc662_fixup_tbl, alc662_fixups, 1); /* automatic parse from the BIOS config */ err = alc662_parse_auto_config(codec); if (err < 0) { @@ -18769,8 +18790,11 @@ static int patch_alc662(struct hda_codec *codec) spec->vmaster_nid = 0x02; codec->patch_ops = alc_patch_ops; - if (board_config == ALC662_AUTO) + if (board_config == ALC662_AUTO) { spec->init_hook = alc662_auto_init; + alc_pick_fixup(codec, alc662_fixup_tbl, alc662_fixups, 0); + } + #ifdef CONFIG_SND_HDA_POWER_SAVE if (!spec->loopback.amplist) spec->loopback.amplist = alc662_loopbacks; -- cgit v1.2.3 From 43365dd81ad90375befc33ea426d3448a04f0c38 Mon Sep 17 00:00:00 2001 From: Valentine Sinitsyn Date: Fri, 1 Oct 2010 22:24:08 +0600 Subject: ALSA: hda - Added fixup for Lenovo Y550P commit d41185882b828896ccecac319c9f65f708baaf0d upstream. Signed-off-by: Valentine Sinitsyn Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 26820cd0ea98..2a085aa9e712 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -18693,6 +18693,7 @@ static const struct alc_fixup alc662_fixups[] = { }; static struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), {} }; -- cgit v1.2.3 From 43c463c71292f424f8ddb9e1852e2b1de0c86eed Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Sun, 10 Oct 2010 22:39:28 -0400 Subject: ALSA: hda: Add speaker pin to automute Acer Aspire 8943G commit 2df03514de41f3bbb5623f2e7f2bf594e49cb2ec upstream. BugLink: https://bugs.launchpad.net/bugs/656625 Add clause for handling Acer Aspire 8943G's subwoofer as additional speaker pin for automuting. Reported-by: RussianNeuroMancer Signed-off-by: Daniel T Chen Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_realtek.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2a085aa9e712..ea8111317297 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -18680,10 +18680,17 @@ static void alc662_auto_init(struct hda_codec *codec) } enum { + ALC662_FIXUP_ASPIRE, ALC662_FIXUP_IDEAPAD, }; static const struct alc_fixup alc662_fixups[] = { + [ALC662_FIXUP_ASPIRE] = { + .pins = (const struct alc_pincfg[]) { + { 0x15, 0x99130112 }, /* subwoofer */ + { } + } + }, [ALC662_FIXUP_IDEAPAD] = { .pins = (const struct alc_pincfg[]) { { 0x17, 0x99130112 }, /* subwoofer */ @@ -18693,6 +18700,7 @@ static const struct alc_fixup alc662_fixups[] = { }; static struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), {} -- cgit v1.2.3 From 3d35ce84b3081199d1202ad36669212c62122cfb Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Sat, 20 Nov 2010 10:20:35 -0500 Subject: ALSA: hda: Add Samsung R720 SSID for subwoofer pin fixup commit a0e90acc657990511c83bc69965bfd3c63386d45 upstream. BugLink: https://launchpad.net/bugs/677830 The original reporter states that the subwoofer does not mute when inserting headphones. We need an entry for his machine's SSID in the subwoofer pin fixup list, so add it there (verified using hda_analyzer). Reported-and-tested-by: i-NoD Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ea8111317297..5af5bff09375 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -18701,6 +18701,7 @@ static const struct alc_fixup alc662_fixups[] = { static struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), + SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), {} -- cgit v1.2.3 From bc23f2c11af8b5d32724fe3e226e3edb0fdf6fb2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 26 Nov 2010 17:11:18 +0100 Subject: ALSA: hda - Use ALC_INIT_DEFAULT for really default initialization commit 5a8cfb4e8ae317d283f84122ed20faa069c5e0c4 upstream. When SKU assid gives no valid bits for 0x38, the driver didn't take any action, so far. This resulted in the missing initialization for external amps, etc, thus the silent output in the end. Especially users hit this problem on ALC888 newly since 2.6.35, where the driver doesn't force to use ALC_INIT_DEFAULT any more. This patch sets the default initialization scheme to use ALC_INIT_DEFAULT when no valid bits are set for SKU assid. Reference: https://bugzilla.redhat.com/show_bug.cgi?id=657388 Reported-and-tested-by: Kyle McMartin Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5af5bff09375..6d15ce471c7c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1391,6 +1391,7 @@ do_sku: spec->init_amp = ALC_INIT_GPIO3; break; case 5: + default: spec->init_amp = ALC_INIT_DEFAULT; break; } -- cgit v1.2.3 From ba9219020fecff721cb7cb6e21defb63ba5c3bf6 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Thu, 25 Nov 2010 00:08:01 -0200 Subject: ALSA: hda - Fix ALC660-VD/ALC861-VD capture/playback mixers commit 7167594a3da7dcc33203b85d62e519594baee390 upstream. The mixer nids passed to alc_auto_create_input_ctls are wrong: 0x15 is a pin, and 0x09 is the ADC on both ALC660-VD/ALC861-VD. Thus with current code, input playback volume/switches and input source mixer controls are not created, and recording doesn't work. Select correct mixers, 0x0b (input playback mixer) and 0x22 (capture source mixer). Reference: https://qa.mandriva.com/show_bug.cgi?id=61159 Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6d15ce471c7c..2626e5c182cc 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -16302,7 +16302,7 @@ static struct alc_config_preset alc861vd_presets[] = { static int alc861vd_auto_create_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { - return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x09, 0); + return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x22, 0); } -- cgit v1.2.3 From 48099f895b702f3c13a9828396e6efa29d0b370c Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 24 Nov 2010 14:17:47 +0100 Subject: ALSA: HDA: Add an extra DAC for Realtek ALC887-VD commit cc1c452e509aefc28f7ad2deed75bc69d4f915f7 upstream. The patch enables ALC887-VD to use the DAC at nid 0x26, which makes it possible to use this DAC for e g Headphone volume. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_realtek.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2626e5c182cc..a074c8e5f23b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -18357,6 +18357,8 @@ static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid) return 0x02; else if (nid >= 0x0c && nid <= 0x0e) return nid - 0x0c + 0x02; + else if (nid == 0x26) /* ALC887-VD has this DAC too */ + return 0x25; else return 0; } @@ -18365,7 +18367,7 @@ static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid) static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac) { - hda_nid_t mix[4]; + hda_nid_t mix[5]; int i, num; num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix)); -- cgit v1.2.3 From bc59d7d4a0c3ab839cd8651ea639702d4d173a4b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 30 Nov 2010 08:14:21 +0100 Subject: ALSA: Fix SNDCTL_DSP_RESET ioctl for OSS emulation commit 60686aa0086a14f8b15c83a09f3df1eebe3aab3c upstream. In OSS emulation, SNDCTL_DSP_RESET ioctl needs the reset of the internal buffer state in addition to drop of the running streams. Otherwise the succeeding access becomes inconsistent. Tested-by: Amit Nagal Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/core/oss/pcm_oss.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 5c8c7dff8ede..aed06c90a96a 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1510,16 +1510,19 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file) { struct snd_pcm_substream *substream; + struct snd_pcm_runtime *runtime; + int i; - substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; - if (substream != NULL) { - snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); - substream->runtime->oss.prepare = 1; - } - substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; - if (substream != NULL) { + for (i = 0; i < 2; i++) { + substream = pcm_oss_file->streams[i]; + if (!substream) + continue; + runtime = substream->runtime; snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); - substream->runtime->oss.prepare = 1; + runtime->oss.prepare = 1; + runtime->oss.buffer_used = 0; + runtime->oss.prev_hw_ptr_period = 0; + runtime->oss.period_ptr = 0; } return 0; } -- cgit v1.2.3 From bf2f177bdb68b531279f73f3b166360bbc22c747 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Wed, 1 Dec 2010 19:16:07 -0500 Subject: ALSA: hda: Use "alienware" model quirk for another SSID commit 0defe09ca70daccdc83abd9c3c24cd89ae6a1141 upstream. BugLink: https://launchpad.net/bugs/683695 The original reporter states that headphone jacks do not appear to work. Upon inspecting his codec dump, and upon further testing, it is confirmed that the "alienware" model quirk is correct. Reported-and-tested-by: Cody Thierauf Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_sigmatel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 0d69d8edcd8b..364848ef02ff 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1625,6 +1625,8 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { static struct snd_pci_quirk stac92hd73xx_codec_id_cfg_tbl[] = { SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a1, "Alienware M17x", STAC_ALIENWARE_M17X), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x043a, + "Alienware M17x", STAC_ALIENWARE_M17X), {} /* terminator */ }; -- cgit v1.2.3 From c7ec3b059493edf4fc7cdaf4ce7a7883617cefb3 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 28 Oct 2010 12:34:21 +0200 Subject: netfilter: nf_conntrack: allow nf_ct_alloc_hashtable() to get highmem pages commit 6b1686a71e3158d3c5f125260effce171cc7852b upstream. commit ea781f197d6a8 (use SLAB_DESTROY_BY_RCU and get rid of call_rcu()) did a mistake in __vmalloc() call in nf_ct_alloc_hashtable(). I forgot to add __GFP_HIGHMEM, so pages were taken from LOWMEM only. Signed-off-by: Eric Dumazet Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/netfilter/nf_conntrack_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index eeeb8bc73982..0d7a594728bc 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1252,7 +1252,8 @@ void *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced, int nulls) if (!hash) { *vmalloced = 1; printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n"); - hash = __vmalloc(sz, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL); + hash = __vmalloc(sz, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, + PAGE_KERNEL); } if (hash && nulls) -- cgit v1.2.3 From d4587674b6ade7e1910ae70284c99239bff84ead Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Fri, 12 Nov 2010 08:26:06 +0100 Subject: netfilter: NF_HOOK_COND has wrong conditional commit ac5aa2e3332ec04889074afdbd1479424d0227a5 upstream. The NF_HOOK_COND returns 0 when it shouldn't due to what I believe to be an error in the code as the order of operations is not what was intended. C will evalutate == before =. Which means ret is getting set to the bool result, rather than the return value of the function call. The code says if (ret = function() == 1) when it meant to say: if ((ret = function()) == 1) Normally the compiler would warn, but it doesn't notice it because its a actually complex conditional and so the wrong code is wrapped in an explict set of () [exactly what the compiler wants you to do if this was intentional]. Fixing this means that errors when netfilter denies a packet get propagated back up the stack rather than lost. Problem introduced by commit 2249065f (netfilter: get rid of the grossness in netfilter.h). Signed-off-by: Eric Paris Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/linux/netfilter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 89341c32631a..03317c8d4077 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -215,7 +215,7 @@ NF_HOOK_COND(uint8_t pf, unsigned int hook, struct sk_buff *skb, int ret; if (!cond || - (ret = nf_hook_thresh(pf, hook, skb, in, out, okfn, INT_MIN) == 1)) + ((ret = nf_hook_thresh(pf, hook, skb, in, out, okfn, INT_MIN)) == 1)) ret = okfn(skb); return ret; } -- cgit v1.2.3 From 009c1847bbc6a87c995d8ad5f575f2648b76222a Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Thu, 11 Nov 2010 14:05:19 -0800 Subject: radix-tree: fix RCU bug commit 27d20fddc8af539464fc3ba499d6a830054c3bd6 upstream. Salman Qazi describes the following radix-tree bug: In the following case, we get can get a deadlock: 0. The radix tree contains two items, one has the index 0. 1. The reader (in this case find_get_pages) takes the rcu_read_lock. 2. The reader acquires slot(s) for item(s) including the index 0 item. 3. The non-zero index item is deleted, and as a consequence the other item is moved to the root of the tree. The place where it used to be is queued for deletion after the readers finish. 3b. The zero item is deleted, removing it from the direct slot, it remains in the rcu-delayed indirect node. 4. The reader looks at the index 0 slot, and finds that the page has 0 ref count 5. The reader looks at it again, hoping that the item will either be freed or the ref count will increase. This never happens, as the slot it is looking at will never be updated. Also, this slot can never be reclaimed because the reader is holding rcu_read_lock and is in an infinite loop. The fix is to re-use the same "indirect" pointer case that requires a slot lookup retry into a general "retry the lookup" bit. Signed-off-by: Nick Piggin Reported-by: Salman Qazi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/linux/radix-tree.h | 36 +++++++++++---------- lib/radix-tree.c | 78 ++++++++++++++++++++++++++++++++-------------- mm/filemap.c | 26 ++++++---------- 3 files changed, 84 insertions(+), 56 deletions(-) diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index 55ca73cf25e5..8a8de14626c7 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h @@ -36,17 +36,6 @@ * RCU. */ #define RADIX_TREE_INDIRECT_PTR 1 -#define RADIX_TREE_RETRY ((void *)-1UL) - -static inline void *radix_tree_ptr_to_indirect(void *ptr) -{ - return (void *)((unsigned long)ptr | RADIX_TREE_INDIRECT_PTR); -} - -static inline void *radix_tree_indirect_to_ptr(void *ptr) -{ - return (void *)((unsigned long)ptr & ~RADIX_TREE_INDIRECT_PTR); -} static inline int radix_tree_is_indirect_ptr(void *ptr) { @@ -138,16 +127,29 @@ do { \ * removed. * * For use with radix_tree_lookup_slot(). Caller must hold tree at least read - * locked across slot lookup and dereference. More likely, will be used with - * radix_tree_replace_slot(), as well, so caller will hold tree write locked. + * locked across slot lookup and dereference. Not required if write lock is + * held (ie. items cannot be concurrently inserted). + * + * radix_tree_deref_retry must be used to confirm validity of the pointer if + * only the read lock is held. */ static inline void *radix_tree_deref_slot(void **pslot) { - void *ret = rcu_dereference(*pslot); - if (unlikely(radix_tree_is_indirect_ptr(ret))) - ret = RADIX_TREE_RETRY; - return ret; + return rcu_dereference(*pslot); } + +/** + * radix_tree_deref_retry - check radix_tree_deref_slot + * @arg: pointer returned by radix_tree_deref_slot + * Returns: 0 if retry is not required, otherwise retry is required + * + * radix_tree_deref_retry must be used with radix_tree_deref_slot. + */ +static inline int radix_tree_deref_retry(void *arg) +{ + return unlikely((unsigned long)arg & RADIX_TREE_INDIRECT_PTR); +} + /** * radix_tree_replace_slot - replace item in a slot * @pslot: pointer to slot, returned by radix_tree_lookup_slot diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 05da38bcc298..5f0ed4bb4a5b 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -82,6 +82,16 @@ struct radix_tree_preload { }; static DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads) = { 0, }; +static inline void *ptr_to_indirect(void *ptr) +{ + return (void *)((unsigned long)ptr | RADIX_TREE_INDIRECT_PTR); +} + +static inline void *indirect_to_ptr(void *ptr) +{ + return (void *)((unsigned long)ptr & ~RADIX_TREE_INDIRECT_PTR); +} + static inline gfp_t root_gfp_mask(struct radix_tree_root *root) { return root->gfp_mask & __GFP_BITS_MASK; @@ -263,7 +273,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) return -ENOMEM; /* Increase the height. */ - node->slots[0] = radix_tree_indirect_to_ptr(root->rnode); + node->slots[0] = indirect_to_ptr(root->rnode); /* Propagate the aggregated tag info into the new root */ for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { @@ -274,7 +284,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) newheight = root->height+1; node->height = newheight; node->count = 1; - node = radix_tree_ptr_to_indirect(node); + node = ptr_to_indirect(node); rcu_assign_pointer(root->rnode, node); root->height = newheight; } while (height > root->height); @@ -307,7 +317,7 @@ int radix_tree_insert(struct radix_tree_root *root, return error; } - slot = radix_tree_indirect_to_ptr(root->rnode); + slot = indirect_to_ptr(root->rnode); height = root->height; shift = (height-1) * RADIX_TREE_MAP_SHIFT; @@ -323,8 +333,7 @@ int radix_tree_insert(struct radix_tree_root *root, rcu_assign_pointer(node->slots[offset], slot); node->count++; } else - rcu_assign_pointer(root->rnode, - radix_tree_ptr_to_indirect(slot)); + rcu_assign_pointer(root->rnode, ptr_to_indirect(slot)); } /* Go a level down */ @@ -372,7 +381,7 @@ static void *radix_tree_lookup_element(struct radix_tree_root *root, return NULL; return is_slot ? (void *)&root->rnode : node; } - node = radix_tree_indirect_to_ptr(node); + node = indirect_to_ptr(node); height = node->height; if (index > radix_tree_maxindex(height)) @@ -391,7 +400,7 @@ static void *radix_tree_lookup_element(struct radix_tree_root *root, height--; } while (height > 0); - return is_slot ? (void *)slot:node; + return is_slot ? (void *)slot : indirect_to_ptr(node); } /** @@ -453,7 +462,7 @@ void *radix_tree_tag_set(struct radix_tree_root *root, height = root->height; BUG_ON(index > radix_tree_maxindex(height)); - slot = radix_tree_indirect_to_ptr(root->rnode); + slot = indirect_to_ptr(root->rnode); shift = (height - 1) * RADIX_TREE_MAP_SHIFT; while (height > 0) { @@ -507,7 +516,7 @@ void *radix_tree_tag_clear(struct radix_tree_root *root, shift = (height - 1) * RADIX_TREE_MAP_SHIFT; pathp->node = NULL; - slot = radix_tree_indirect_to_ptr(root->rnode); + slot = indirect_to_ptr(root->rnode); while (height > 0) { int offset; @@ -577,7 +586,7 @@ int radix_tree_tag_get(struct radix_tree_root *root, if (!radix_tree_is_indirect_ptr(node)) return (index == 0); - node = radix_tree_indirect_to_ptr(node); + node = indirect_to_ptr(node); height = node->height; if (index > radix_tree_maxindex(height)) @@ -767,7 +776,7 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results, results[0] = node; return 1; } - node = radix_tree_indirect_to_ptr(node); + node = indirect_to_ptr(node); max_index = radix_tree_maxindex(node->height); @@ -835,7 +844,7 @@ radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results, results[0] = (void **)&root->rnode; return 1; } - node = radix_tree_indirect_to_ptr(node); + node = indirect_to_ptr(node); max_index = radix_tree_maxindex(node->height); @@ -960,7 +969,7 @@ radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results, results[0] = node; return 1; } - node = radix_tree_indirect_to_ptr(node); + node = indirect_to_ptr(node); max_index = radix_tree_maxindex(node->height); @@ -979,7 +988,8 @@ radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results, slot = *(((void ***)results)[ret + i]); if (!slot) continue; - results[ret + nr_found] = rcu_dereference_raw(slot); + results[ret + nr_found] = + indirect_to_ptr(rcu_dereference_raw(slot)); nr_found++; } ret += nr_found; @@ -1029,7 +1039,7 @@ radix_tree_gang_lookup_tag_slot(struct radix_tree_root *root, void ***results, results[0] = (void **)&root->rnode; return 1; } - node = radix_tree_indirect_to_ptr(node); + node = indirect_to_ptr(node); max_index = radix_tree_maxindex(node->height); @@ -1065,7 +1075,7 @@ static inline void radix_tree_shrink(struct radix_tree_root *root) void *newptr; BUG_ON(!radix_tree_is_indirect_ptr(to_free)); - to_free = radix_tree_indirect_to_ptr(to_free); + to_free = indirect_to_ptr(to_free); /* * The candidate node has more than one child, or its child @@ -1078,16 +1088,39 @@ static inline void radix_tree_shrink(struct radix_tree_root *root) /* * We don't need rcu_assign_pointer(), since we are simply - * moving the node from one part of the tree to another. If - * it was safe to dereference the old pointer to it + * moving the node from one part of the tree to another: if it + * was safe to dereference the old pointer to it * (to_free->slots[0]), it will be safe to dereference the new - * one (root->rnode). + * one (root->rnode) as far as dependent read barriers go. */ newptr = to_free->slots[0]; if (root->height > 1) - newptr = radix_tree_ptr_to_indirect(newptr); + newptr = ptr_to_indirect(newptr); root->rnode = newptr; root->height--; + + /* + * We have a dilemma here. The node's slot[0] must not be + * NULLed in case there are concurrent lookups expecting to + * find the item. However if this was a bottom-level node, + * then it may be subject to the slot pointer being visible + * to callers dereferencing it. If item corresponding to + * slot[0] is subsequently deleted, these callers would expect + * their slot to become empty sooner or later. + * + * For example, lockless pagecache will look up a slot, deref + * the page pointer, and if the page is 0 refcount it means it + * was concurrently deleted from pagecache so try the deref + * again. Fortunately there is already a requirement for logic + * to retry the entire slot lookup -- the indirect pointer + * problem (replacing direct root node with an indirect pointer + * also results in a stale slot). So tag the slot as indirect + * to force callers to retry. + */ + if (root->height == 0) + *((unsigned long *)&to_free->slots[0]) |= + RADIX_TREE_INDIRECT_PTR; + radix_tree_node_free(to_free); } } @@ -1124,7 +1157,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) root->rnode = NULL; goto out; } - slot = radix_tree_indirect_to_ptr(slot); + slot = indirect_to_ptr(slot); shift = (height - 1) * RADIX_TREE_MAP_SHIFT; pathp->node = NULL; @@ -1166,8 +1199,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) radix_tree_node_free(to_free); if (pathp->node->count) { - if (pathp->node == - radix_tree_indirect_to_ptr(root->rnode)) + if (pathp->node == indirect_to_ptr(root->rnode)) radix_tree_shrink(root); goto out; } diff --git a/mm/filemap.c b/mm/filemap.c index 20e5642e9f9f..2332bfa3b14c 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -631,7 +631,9 @@ repeat: pagep = radix_tree_lookup_slot(&mapping->page_tree, offset); if (pagep) { page = radix_tree_deref_slot(pagep); - if (unlikely(!page || page == RADIX_TREE_RETRY)) + if (unlikely(!page)) + goto out; + if (radix_tree_deref_retry(page)) goto repeat; if (!page_cache_get_speculative(page)) @@ -647,6 +649,7 @@ repeat: goto repeat; } } +out: rcu_read_unlock(); return page; @@ -764,12 +767,11 @@ repeat: page = radix_tree_deref_slot((void **)pages[i]); if (unlikely(!page)) continue; - /* - * this can only trigger if nr_found == 1, making livelock - * a non issue. - */ - if (unlikely(page == RADIX_TREE_RETRY)) + if (radix_tree_deref_retry(page)) { + if (ret) + start = pages[ret-1]->index; goto restart; + } if (!page_cache_get_speculative(page)) goto repeat; @@ -817,11 +819,7 @@ repeat: page = radix_tree_deref_slot((void **)pages[i]); if (unlikely(!page)) continue; - /* - * this can only trigger if nr_found == 1, making livelock - * a non issue. - */ - if (unlikely(page == RADIX_TREE_RETRY)) + if (radix_tree_deref_retry(page)) goto restart; if (page->mapping == NULL || page->index != index) @@ -874,11 +872,7 @@ repeat: page = radix_tree_deref_slot((void **)pages[i]); if (unlikely(!page)) continue; - /* - * this can only trigger if nr_found == 1, making livelock - * a non issue. - */ - if (unlikely(page == RADIX_TREE_RETRY)) + if (radix_tree_deref_retry(page)) goto restart; if (!page_cache_get_speculative(page)) -- cgit v1.2.3 From c6ec3bc8d63237a1c7873eda3a170710ae241847 Mon Sep 17 00:00:00 2001 From: Ken Chen Date: Thu, 11 Nov 2010 14:05:16 -0800 Subject: latencytop: fix per task accumulator commit 38715258aa2e8cd94bd4aafadc544e5104efd551 upstream. Per task latencytop accumulator prematurely terminates due to erroneous placement of latency_record_count. It should be incremented whenever a new record is allocated instead of increment on every latencytop event. Also fix search iterator to only search known record events instead of blindly searching all pre-allocated space. Signed-off-by: Ken Chen Signed-off-by: Andi Kleen Reviewed-by: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/latencytop.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/kernel/latencytop.c b/kernel/latencytop.c index 877fb306d415..17110a4a4fc2 100644 --- a/kernel/latencytop.c +++ b/kernel/latencytop.c @@ -194,14 +194,7 @@ __account_scheduler_latency(struct task_struct *tsk, int usecs, int inter) account_global_scheduler_latency(tsk, &lat); - /* - * short term hack; if we're > 32 we stop; future we recycle: - */ - tsk->latency_record_count++; - if (tsk->latency_record_count >= LT_SAVECOUNT) - goto out_unlock; - - for (i = 0; i < LT_SAVECOUNT; i++) { + for (i = 0; i < tsk->latency_record_count; i++) { struct latency_record *mylat; int same = 1; @@ -227,8 +220,14 @@ __account_scheduler_latency(struct task_struct *tsk, int usecs, int inter) } } + /* + * short term hack; if we're > 32 we stop; future we recycle: + */ + if (tsk->latency_record_count >= LT_SAVECOUNT) + goto out_unlock; + /* Allocated a new one: */ - i = tsk->latency_record_count; + i = tsk->latency_record_count++; memcpy(&tsk->latency_record[i], &lat, sizeof(struct latency_record)); out_unlock: -- cgit v1.2.3 From 533f966c7aeae378188c9ec5b8635a4afabb8ea3 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Thu, 11 Nov 2010 14:05:15 -0800 Subject: mm/vfs: revalidate page->mapping in do_generic_file_read() commit 8d056cb965b8fb7c53c564abf28b1962d1061cd3 upstream. 70 hours into some stress tests of a 2.6.32-based enterprise kernel, we ran into a NULL dereference in here: int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc, unsigned long from) { ----> struct inode *inode = page->mapping->host; It looks like page->mapping was the culprit. (xmon trace is below). After closer examination, I realized that do_generic_file_read() does a find_get_page(), and eventually locks the page before calling block_is_partially_uptodate(). However, it doesn't revalidate the page->mapping after the page is locked. So, there's a small window between the find_get_page() and ->is_partially_uptodate() where the page could get truncated and page->mapping cleared. We _have_ a reference, so it can't get reclaimed, but it certainly can be truncated. I think the correct thing is to check page->mapping after the trylock_page(), and jump out if it got truncated. This patch has been running in the test environment for a month or so now, and we have not seen this bug pop up again. xmon info: 1f:mon> e cpu 0x1f: Vector: 300 (Data Access) at [c0000002ae36f770] pc: c0000000001e7a6c: .block_is_partially_uptodate+0xc/0x100 lr: c000000000142944: .generic_file_aio_read+0x1e4/0x770 sp: c0000002ae36f9f0 msr: 8000000000009032 dar: 0 dsisr: 40000000 current = 0xc000000378f99e30 paca = 0xc000000000f66300 pid = 21946, comm = bash 1f:mon> r R00 = 0025c0500000006d R16 = 0000000000000000 R01 = c0000002ae36f9f0 R17 = c000000362cd3af0 R02 = c000000000e8cd80 R18 = ffffffffffffffff R03 = c0000000031d0f88 R19 = 0000000000000001 R04 = c0000002ae36fa68 R20 = c0000003bb97b8a0 R05 = 0000000000000000 R21 = c0000002ae36fa68 R06 = 0000000000000000 R22 = 0000000000000000 R07 = 0000000000000001 R23 = c0000002ae36fbb0 R08 = 0000000000000002 R24 = 0000000000000000 R09 = 0000000000000000 R25 = c000000362cd3a80 R10 = 0000000000000000 R26 = 0000000000000002 R11 = c0000000001e7b60 R27 = 0000000000000000 R12 = 0000000042000484 R28 = 0000000000000001 R13 = c000000000f66300 R29 = c0000003bb97b9b8 R14 = 0000000000000001 R30 = c000000000e28a08 R15 = 000000000000ffff R31 = c0000000031d0f88 pc = c0000000001e7a6c .block_is_partially_uptodate+0xc/0x100 lr = c000000000142944 .generic_file_aio_read+0x1e4/0x770 msr = 8000000000009032 cr = 22000488 ctr = c0000000001e7a60 xer = 0000000020000000 trap = 300 dar = 0000000000000000 dsisr = 40000000 1f:mon> t [link register ] c000000000142944 .generic_file_aio_read+0x1e4/0x770 [c0000002ae36f9f0] c000000000142a14 .generic_file_aio_read+0x2b4/0x770 (unreliable) [c0000002ae36fb40] c0000000001b03e4 .do_sync_read+0xd4/0x160 [c0000002ae36fce0] c0000000001b153c .vfs_read+0xec/0x1f0 [c0000002ae36fd80] c0000000001b1768 .SyS_read+0x58/0xb0 [c0000002ae36fe30] c00000000000852c syscall_exit+0x0/0x40 --- Exception: c00 (System Call) at 00000080a840bc54 SP (fffca15df30) is in userspace 1f:mon> di c0000000001e7a6c c0000000001e7a6c e9290000 ld r9,0(r9) c0000000001e7a70 418200c0 beq c0000000001e7b30 # .block_is_partially_uptodate+0xd0/0x100 c0000000001e7a74 e9440008 ld r10,8(r4) c0000000001e7a78 78a80020 clrldi r8,r5,32 c0000000001e7a7c 3c000001 lis r0,1 c0000000001e7a80 812900a8 lwz r9,168(r9) c0000000001e7a84 39600001 li r11,1 c0000000001e7a88 7c080050 subf r0,r8,r0 c0000000001e7a8c 7f805040 cmplw cr7,r0,r10 c0000000001e7a90 7d6b4830 slw r11,r11,r9 c0000000001e7a94 796b0020 clrldi r11,r11,32 c0000000001e7a98 419d00a8 bgt cr7,c0000000001e7b40 # .block_is_partially_uptodate+0xe0/0x100 c0000000001e7a9c 7fa55840 cmpld cr7,r5,r11 c0000000001e7aa0 7d004214 add r8,r0,r8 c0000000001e7aa4 79080020 clrldi r8,r8,32 c0000000001e7aa8 419c0078 blt cr7,c0000000001e7b20 # .block_is_partially_uptodate+0xc0/0x100 Signed-off-by: Dave Hansen Reviewed-by: Minchan Kim Reviewed-by: Johannes Weiner Acked-by: Rik van Riel Cc: Cc: Cc: Christoph Hellwig Cc: Al Viro Cc: Minchan Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- mm/filemap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mm/filemap.c b/mm/filemap.c index 2332bfa3b14c..183d2d439b28 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1010,6 +1010,9 @@ find_page: goto page_not_up_to_date; if (!trylock_page(page)) goto page_not_up_to_date; + /* Did it get truncated before we got the lock? */ + if (!page->mapping) + goto page_not_up_to_date_locked; if (!mapping->a_ops->is_partially_uptodate(page, desc, offset)) goto page_not_up_to_date_locked; -- cgit v1.2.3 From 6d166dd8e4157e9381a2d4dd2f77eda2600fa783 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 10 Nov 2010 14:36:25 +0100 Subject: bio: take care not overflow page count when mapping/copying user data commit cb4644cac4a2797afc847e6c92736664d4b0ea34 upstream. If the iovec is being set up in a way that causes uaddr + PAGE_SIZE to overflow, we could end up attempting to map a huge number of pages. Check for this invalid input type. Reported-by: Dan Rosenberg Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/bio.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/fs/bio.c b/fs/bio.c index 75ea4c3b1d10..b3e017434068 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -834,6 +834,12 @@ struct bio *bio_copy_user_iov(struct request_queue *q, end = (uaddr + iov[i].iov_len + PAGE_SIZE - 1) >> PAGE_SHIFT; start = uaddr >> PAGE_SHIFT; + /* + * Overflow, abort + */ + if (end < start) + return ERR_PTR(-EINVAL); + nr_pages += end - start; len += iov[i].iov_len; } @@ -961,6 +967,12 @@ static struct bio *__bio_map_user_iov(struct request_queue *q, unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; unsigned long start = uaddr >> PAGE_SHIFT; + /* + * Overflow, abort + */ + if (end < start) + return ERR_PTR(-EINVAL); + nr_pages += end - start; /* * buffer must be aligned to at least hardsector size for now @@ -988,7 +1000,7 @@ static struct bio *__bio_map_user_iov(struct request_queue *q, unsigned long start = uaddr >> PAGE_SHIFT; const int local_nr_pages = end - start; const int page_limit = cur_page + local_nr_pages; - + ret = get_user_pages_fast(uaddr, local_nr_pages, write_to_vm, &pages[cur_page]); if (ret < local_nr_pages) { -- cgit v1.2.3 From b7de29c5fd5a31d6fca4d9c86a2c92b4da4df626 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 17 Nov 2010 02:49:40 -0500 Subject: drm/radeon/kms/atom: set sane defaults in atombios_get_encoder_mode() commit c7a71fc761551dc8be8543f14a90d08cda4e77f9 upstream. If there was no connector mapped to the encoder, atombios_get_encoder_mode() returned 0 which is the id for DP. Return something sane instead based on the encoder id. This avoids hitting the DP paths on non-DP encoders. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/radeon_encoders.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 68a3d79a73d4..d7d06f14db69 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -626,11 +626,23 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) struct drm_connector *connector; struct radeon_connector *radeon_connector; struct radeon_connector_atom_dig *dig_connector; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); connector = radeon_get_connector_for_encoder(encoder); - if (!connector) - return 0; - + if (!connector) { + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + return ATOM_ENCODER_MODE_DVI; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + default: + return ATOM_ENCODER_MODE_CRT; + } + } radeon_connector = to_radeon_connector(connector); switch (connector->connector_type) { -- cgit v1.2.3 From 2aa9f3ac2b1027717eb57010b5931d1d85b216fb Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 30 Nov 2010 19:11:45 -0500 Subject: drm/radeon/kms: fix typos in disabled vbios code commit 0ec80d645661dda50acd417bdfcb33df2e5dd31e upstream. 6xx/7xx was hitting the wrong BUS_CNTL reg and bits. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/r600_reg.h | 1 + drivers/gpu/drm/radeon/radeon_bios.c | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_reg.h b/drivers/gpu/drm/radeon/r600_reg.h index d84612ae47e0..33cda016b083 100644 --- a/drivers/gpu/drm/radeon/r600_reg.h +++ b/drivers/gpu/drm/radeon/r600_reg.h @@ -86,6 +86,7 @@ #define R600_HDP_NONSURFACE_BASE 0x2c04 #define R600_BUS_CNTL 0x5420 +# define R600_BIOS_ROM_DIS (1 << 1) #define R600_CONFIG_CNTL 0x5424 #define R600_CONFIG_MEMSIZE 0x5428 #define R600_CONFIG_F0_BASE 0x542C diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 2c9213739999..89a8eed1fb84 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -130,6 +130,7 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) } return true; } + static bool r700_read_disabled_bios(struct radeon_device *rdev) { uint32_t viph_control; @@ -143,7 +144,7 @@ static bool r700_read_disabled_bios(struct radeon_device *rdev) bool r; viph_control = RREG32(RADEON_VIPH_CONTROL); - bus_cntl = RREG32(RADEON_BUS_CNTL); + bus_cntl = RREG32(R600_BUS_CNTL); d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); @@ -152,7 +153,7 @@ static bool r700_read_disabled_bios(struct radeon_device *rdev) /* disable VIP */ WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); /* enable the rom */ - WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); + WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); /* Disable VGA mode */ WREG32(AVIVO_D1VGA_CONTROL, (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | @@ -191,7 +192,7 @@ static bool r700_read_disabled_bios(struct radeon_device *rdev) cg_spll_status = RREG32(R600_CG_SPLL_STATUS); } WREG32(RADEON_VIPH_CONTROL, viph_control); - WREG32(RADEON_BUS_CNTL, bus_cntl); + WREG32(R600_BUS_CNTL, bus_cntl); WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); @@ -216,7 +217,7 @@ static bool r600_read_disabled_bios(struct radeon_device *rdev) bool r; viph_control = RREG32(RADEON_VIPH_CONTROL); - bus_cntl = RREG32(RADEON_BUS_CNTL); + bus_cntl = RREG32(R600_BUS_CNTL); d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); @@ -231,7 +232,7 @@ static bool r600_read_disabled_bios(struct radeon_device *rdev) /* disable VIP */ WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); /* enable the rom */ - WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); + WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); /* Disable VGA mode */ WREG32(AVIVO_D1VGA_CONTROL, (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | @@ -262,7 +263,7 @@ static bool r600_read_disabled_bios(struct radeon_device *rdev) /* restore regs */ WREG32(RADEON_VIPH_CONTROL, viph_control); - WREG32(RADEON_BUS_CNTL, bus_cntl); + WREG32(R600_BUS_CNTL, bus_cntl); WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); -- cgit v1.2.3 From 7b86e65e74572b8a2935e136a901a527786d2772 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 30 Nov 2010 00:15:10 -0500 Subject: drm/radeon/kms: add workaround for dce3 ddc line vbios bug commit 3074adc8b6d9bf28b574a58241b958057a69a7a0 upstream. fixes: https://bugzilla.kernel.org/show_bug.cgi?id=23752 [AK: Dropped hunk for non existing i2c code in .35] Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/radeon_atombios.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index d7c18e5233e5..42d876a5751b 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -84,6 +84,14 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev for (i = 0; i < num_indices; i++) { gpio = &i2c_info->asGPIO_Info[i]; + /* some DCE3 boards have bad data for this entry */ + if (ASIC_IS_DCE3(rdev)) { + if ((i == 4) && + (gpio->usClkMaskRegisterIndex == 0x1fda) && + (gpio->sucI2cId.ucAccess == 0x94)) + gpio->sucI2cId.ucAccess = 0x14; + } + if (gpio->sucI2cId.ucAccess == id) { i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; -- cgit v1.2.3 From 73b7f671413df8be86082244b0ae55516097eebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Tue, 9 Nov 2010 11:50:05 +0100 Subject: drm/radeon/kms: Fix retrying ttm_bo_init() after it failed once. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 2b66b50b12cabc05f05543e792d4c9c2465d5702 upstream. If ttm_bo_init() returns failure, it already destroyed the BO, so we need to retry from scratch. Signed-off-by: Michel Dänzer Tested-by: Markus Trippelsdorf Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/radeon_object.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index d33b6c91ceda..55051256c77f 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -102,6 +102,8 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj, type = ttm_bo_type_device; } *bo_ptr = NULL; + +retry: bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); if (bo == NULL) return -ENOMEM; @@ -109,8 +111,6 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj, bo->gobj = gobj; bo->surface_reg = -1; INIT_LIST_HEAD(&bo->list); - -retry: radeon_ttm_placement_from_domain(bo, domain); /* Kernel allocation are uninterruptible */ mutex_lock(&rdev->vram_mutex); -- cgit v1.2.3 From f79f5c7c8c2fd31a9e00586aa5e5ed443af88cef Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 30 Nov 2010 15:46:47 -0500 Subject: drm/radeon/kms: fix interlaced and doublescan handling commit c49948f4bd39e27dd06a1cdb0c3743ca2a734f5e upstream. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/radeon_connectors.c | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index adccbc2c202c..346dc6d1b694 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -1083,6 +1083,8 @@ radeon_add_atom_connector(struct drm_device *dev, rdev->mode_info.load_detect_property, 1); connector->polled = DRM_CONNECTOR_POLL_CONNECT; + connector->interlace_allowed = true; + connector->doublescan_allowed = true; break; case DRM_MODE_CONNECTOR_DVIA: drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); @@ -1096,6 +1098,8 @@ radeon_add_atom_connector(struct drm_device *dev, drm_connector_attach_property(&radeon_connector->base, rdev->mode_info.load_detect_property, 1); + connector->interlace_allowed = true; + connector->doublescan_allowed = true; break; case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_DVID: @@ -1122,6 +1126,11 @@ radeon_add_atom_connector(struct drm_device *dev, rdev->mode_info.load_detect_property, 1); } + connector->interlace_allowed = true; + if (connector_type == DRM_MODE_CONNECTOR_DVII) + connector->doublescan_allowed = true; + else + connector->doublescan_allowed = false; break; case DRM_MODE_CONNECTOR_HDMIA: case DRM_MODE_CONNECTOR_HDMIB: @@ -1142,6 +1151,11 @@ radeon_add_atom_connector(struct drm_device *dev, rdev->mode_info.coherent_mode_property, 1); subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = true; + if (connector_type == DRM_MODE_CONNECTOR_HDMIB) + connector->doublescan_allowed = true; + else + connector->doublescan_allowed = false; break; case DRM_MODE_CONNECTOR_DisplayPort: case DRM_MODE_CONNECTOR_eDP: @@ -1172,6 +1186,9 @@ radeon_add_atom_connector(struct drm_device *dev, drm_connector_attach_property(&radeon_connector->base, rdev->mode_info.coherent_mode_property, 1); + connector->interlace_allowed = true; + /* in theory with a DP to VGA converter... */ + connector->doublescan_allowed = false; break; case DRM_MODE_CONNECTOR_SVIDEO: case DRM_MODE_CONNECTOR_Composite: @@ -1187,6 +1204,8 @@ radeon_add_atom_connector(struct drm_device *dev, rdev->mode_info.tv_std_property, radeon_atombios_get_tv_info(rdev)); } + connector->interlace_allowed = false; + connector->doublescan_allowed = false; break; case DRM_MODE_CONNECTOR_LVDS: radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); @@ -1206,6 +1225,8 @@ radeon_add_atom_connector(struct drm_device *dev, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN); subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; break; } @@ -1277,6 +1298,8 @@ radeon_add_legacy_connector(struct drm_device *dev, rdev->mode_info.load_detect_property, 1); connector->polled = DRM_CONNECTOR_POLL_CONNECT; + connector->interlace_allowed = true; + connector->doublescan_allowed = true; break; case DRM_MODE_CONNECTOR_DVIA: drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); @@ -1290,6 +1313,8 @@ radeon_add_legacy_connector(struct drm_device *dev, drm_connector_attach_property(&radeon_connector->base, rdev->mode_info.load_detect_property, 1); + connector->interlace_allowed = true; + connector->doublescan_allowed = true; break; case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_DVID: @@ -1307,6 +1332,11 @@ radeon_add_legacy_connector(struct drm_device *dev, 1); } subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = true; + if (connector_type == DRM_MODE_CONNECTOR_DVII) + connector->doublescan_allowed = true; + else + connector->doublescan_allowed = false; break; case DRM_MODE_CONNECTOR_SVIDEO: case DRM_MODE_CONNECTOR_Composite: @@ -1329,6 +1359,8 @@ radeon_add_legacy_connector(struct drm_device *dev, rdev->mode_info.tv_std_property, radeon_combios_get_tv_info(rdev)); } + connector->interlace_allowed = false; + connector->doublescan_allowed = false; break; case DRM_MODE_CONNECTOR_LVDS: drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); @@ -1342,6 +1374,8 @@ radeon_add_legacy_connector(struct drm_device *dev, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN); subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; break; } -- cgit v1.2.3 From c9b14e575935b3540e08f4467cf6588be2669710 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Tue, 14 Dec 2010 23:40:11 +0100 Subject: exec: make argv/envp memory visible to oom-killer commit 3c77f845722158206a7209c45ccddc264d19319c upstream. Brad Spengler published a local memory-allocation DoS that evades the OOM-killer (though not the virtual memory RLIMIT): http://www.grsecurity.net/~spender/64bit_dos.c execve()->copy_strings() can allocate a lot of memory, but this is not visible to oom-killer, nobody can see the nascent bprm->mm and take it into account. With this patch get_arg_page() increments current's MM_ANONPAGES counter every time we allocate the new page for argv/envp. When do_execve() succeds or fails, we change this counter back. Technically this is not 100% correct, we can't know if the new page is swapped out and turn MM_ANONPAGES into MM_SWAPENTS, but I don't think this really matters and everything becomes correct once exec changes ->mm or fails. Compared to upstream: before 2.6.36 kernel, oom-killer's badness() takes mm->total_vm into account and nothing else. So acct_arg_size() has to play with this counter too. Reported-by: Brad Spengler Signed-off-by: Andi Kleen Reviewed-and-discussed-by: KOSAKI Motohiro Signed-off-by: Oleg Nesterov Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/exec.c | 28 ++++++++++++++++++++++++++-- include/linux/binfmts.h | 1 + 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 956bd37743cd..53a5fc558bf9 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -158,6 +158,21 @@ out: #ifdef CONFIG_MMU +static void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) +{ + struct mm_struct *mm = current->mm; + long diff = (long)(pages - bprm->vma_pages); + + if (!mm || !diff) + return; + + bprm->vma_pages = pages; + + down_write(&mm->mmap_sem); + mm->total_vm += diff; + up_write(&mm->mmap_sem); +} + static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, int write) { @@ -180,6 +195,8 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start; struct rlimit *rlim; + acct_arg_size(bprm, size / PAGE_SIZE); + /* * We've historically supported up to 32 pages (ARG_MAX) * of argument strings even with small stacks @@ -270,6 +287,10 @@ static bool valid_arg_len(struct linux_binprm *bprm, long len) #else +static inline void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) +{ +} + static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, int write) { @@ -991,6 +1012,7 @@ int flush_old_exec(struct linux_binprm * bprm) /* * Release all of the old mmap stuff */ + acct_arg_size(bprm, 0); retval = exec_mmap(bprm->mm); if (retval) goto out; @@ -1415,8 +1437,10 @@ int do_execve(char * filename, return retval; out: - if (bprm->mm) - mmput (bprm->mm); + if (bprm->mm) { + acct_arg_size(bprm, 0); + mmput(bprm->mm); + } out_file: if (bprm->file) { diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index c809e286d213..39798c65c238 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -29,6 +29,7 @@ struct linux_binprm{ char buf[BINPRM_BUF_SIZE]; #ifdef CONFIG_MMU struct vm_area_struct *vma; + unsigned long vma_pages; #else # define MAX_ARG_PAGES 32 struct page *page[MAX_ARG_PAGES]; -- cgit v1.2.3 From 64e05f5440698463a93cb6bb97f71d7b8b7fee65 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Tue, 30 Nov 2010 20:56:02 +0100 Subject: exec: copy-and-paste the fixes into compat_do_execve() paths commit 114279be2120a916e8a04feeb2ac976a10016f2f upstream. Note: this patch targets 2.6.37 and tries to be as simple as possible. That is why it adds more copy-and-paste horror into fs/compat.c and uglifies fs/exec.c, this will be cleanuped later. compat_copy_strings() plays with bprm->vma/mm directly and thus has two problems: it lacks the RLIMIT_STACK check and argv/envp memory is not visible to oom killer. Export acct_arg_size() and get_arg_page(), change compat_copy_strings() to use get_arg_page(), change compat_do_execve() to do acct_arg_size(0) as do_execve() does. Add the fatal_signal_pending/cond_resched checks into compat_count() and compat_copy_strings(), this matches the code in fs/exec.c and certainly makes sense. Signed-off-by: Oleg Nesterov Cc: KOSAKI Motohiro Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/compat.c | 28 +++++++++++++++------------- fs/exec.c | 8 ++++---- include/linux/binfmts.h | 4 ++++ 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/fs/compat.c b/fs/compat.c index af7c2301a2ec..34bf9fcac319 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1376,6 +1376,10 @@ static int compat_count(compat_uptr_t __user *argv, int max) argv++; if (i++ >= max) return -E2BIG; + + if (fatal_signal_pending(current)) + return -ERESTARTNOHAND; + cond_resched(); } } return i; @@ -1417,6 +1421,12 @@ static int compat_copy_strings(int argc, compat_uptr_t __user *argv, while (len > 0) { int offset, bytes_to_copy; + if (fatal_signal_pending(current)) { + ret = -ERESTARTNOHAND; + goto out; + } + cond_resched(); + offset = pos % PAGE_SIZE; if (offset == 0) offset = PAGE_SIZE; @@ -1433,18 +1443,8 @@ static int compat_copy_strings(int argc, compat_uptr_t __user *argv, if (!kmapped_page || kpos != (pos & PAGE_MASK)) { struct page *page; -#ifdef CONFIG_STACK_GROWSUP - ret = expand_stack_downwards(bprm->vma, pos); - if (ret < 0) { - /* We've exceed the stack rlimit. */ - ret = -E2BIG; - goto out; - } -#endif - ret = get_user_pages(current, bprm->mm, pos, - 1, 1, 1, &page, NULL); - if (ret <= 0) { - /* We've exceed the stack rlimit. */ + page = get_arg_page(bprm, pos, 1); + if (!page) { ret = -E2BIG; goto out; } @@ -1565,8 +1565,10 @@ int compat_do_execve(char * filename, return retval; out: - if (bprm->mm) + if (bprm->mm) { + acct_arg_size(bprm, 0); mmput(bprm->mm); + } out_file: if (bprm->file) { diff --git a/fs/exec.c b/fs/exec.c index 53a5fc558bf9..dd8cabd27ff5 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -158,7 +158,7 @@ out: #ifdef CONFIG_MMU -static void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) +void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) { struct mm_struct *mm = current->mm; long diff = (long)(pages - bprm->vma_pages); @@ -173,7 +173,7 @@ static void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) up_write(&mm->mmap_sem); } -static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, +struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, int write) { struct page *page; @@ -287,11 +287,11 @@ static bool valid_arg_len(struct linux_binprm *bprm, long len) #else -static inline void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) +void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) { } -static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, +struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, int write) { struct page *page; diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 39798c65c238..074b620d5d8b 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -60,6 +60,10 @@ struct linux_binprm{ unsigned long loader, exec; }; +extern void acct_arg_size(struct linux_binprm *bprm, unsigned long pages); +extern struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, + int write); + #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0 #define BINPRM_FLAGS_ENFORCE_NONDUMP (1 << BINPRM_FLAGS_ENFORCE_NONDUMP_BIT) -- cgit v1.2.3 From df5b9f1cdee1c24106013c18c195ca6a98022291 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 24 Nov 2010 17:37:17 +0000 Subject: drm/i915/sdvo: Always add a 30ms delay to make SDVO TV detection reliable commit ba84cd1f2b5dd49bda9300c5a11373f7e14c3c66 upstream. Commit d09c23de intended to add a 30ms delay to give the ADD time to detect any TVs connected. However, it used the sdvo->is_tv flag to do so which is dependent upon the previous detection result and not whether the output supports TVs. Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/i915/intel_sdvo.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 76993ac16cc1..b7485d080cce 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1580,10 +1580,10 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0); - if (sdvo_priv->is_tv) { - /* add 30ms delay when the output type is SDVO-TV */ - mdelay(30); - } + /* add 30ms delay when the output type might be TV */ + if (sdvo_priv->caps.output_flags & + (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_CVBS0)) + mdelay(30); status = intel_sdvo_read_response(intel_encoder, &response, 2); DRM_DEBUG_KMS("SDVO response %d %d\n", response & 0xff, response >> 8); -- cgit v1.2.3 From abf171a0b317ba700938a81d534e57a05e1a6546 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sat, 28 Aug 2010 11:04:32 +0200 Subject: intel-gtt: fix gtt_total_entries detection commit e5e408fc94595aab897f613b6f4e2f5b36870a6f upstream. In commit f1befe71 Chris Wilson added some code to clear the full gtt on g33/pineview instead of just the mappable part. The code looks like it was copy-pasted from agp/intel-gtt.c, at least an identical piece of code is still there (in intel_i830_init_gtt_entries). This lead to a regression in 2.6.35 which was supposedly fixed in commit e7b96f28 Now this commit makes absolutely no sense to me. It seems to be slightly confused about chipset generations - it references docs for 4th gen but the regression concerns 3rd gen g33. Luckily the the g33 gmch docs are available with the GMCH Graphics Control pci config register definitions. The other (bigger problem) is that the new check in there uses the i830 stolen mem bits (.5M, 1M or 8M of stolen mem). They are different since the i855GM. The most likely case is that it hits the 512M fallback, which was probably the right thing for the boxes this was tested on. So the original approach by Chris Wilson seems to be wrong and the current code is definitely wrong. There is a third approach by Jesse Barnes from his RFC patch "Who wants a bigger GTT mapping range?" where he simply shoves g33 in the same clause like later chipset generations. I've asked him and Jesse confirmed that this should work. So implement it. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=16891$ Tested-by: Anisse Astier Signed-off-by: Anisse Astier Signed-off-by: Daniel Vetter Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/char/agp/intel-gtt.c | 63 +++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 86f5337aabdf..16cfbab341bf 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -531,7 +531,7 @@ static void intel_i830_init_gtt_entries(void) pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); - if (IS_I965) { + if (IS_G33 || IS_I965) { u32 pgetbl_ctl; pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); @@ -564,22 +564,6 @@ static void intel_i830_init_gtt_entries(void) size = 512; } size += 4; /* add in BIOS popup space */ - } else if (IS_G33 && !IS_PINEVIEW) { - /* G33's GTT size defined in gmch_ctrl */ - switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { - case G33_PGETBL_SIZE_1M: - size = 1024; - break; - case G33_PGETBL_SIZE_2M: - size = 2048; - break; - default: - dev_info(&agp_bridge->dev->dev, - "unknown page table size 0x%x, assuming 512KB\n", - (gmch_ctrl & G33_PGETBL_SIZE_MASK)); - size = 512; - } - size += 4; } else if (IS_G4X || IS_PINEVIEW) { /* On 4 series hardware, GTT stolen is separate from graphics * stolen, ignore it in stolen gtt entries counting. However, @@ -1250,24 +1234,31 @@ static int intel_i915_get_gtt_size(void) int size; if (IS_G33) { - u16 gmch_ctrl; + u32 pgetbl_ctl; + pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); - /* G33's GTT size defined in gmch_ctrl */ - pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); - switch (gmch_ctrl & I830_GMCH_GMS_MASK) { - case I830_GMCH_GMS_STOLEN_512: + switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) { + case I965_PGETBL_SIZE_128KB: + size = 128; + break; + case I965_PGETBL_SIZE_256KB: + size = 256; + break; + case I965_PGETBL_SIZE_512KB: size = 512; break; - case I830_GMCH_GMS_STOLEN_1024: + case I965_PGETBL_SIZE_1MB: size = 1024; break; - case I830_GMCH_GMS_STOLEN_8192: - size = 8*1024; + case I965_PGETBL_SIZE_2MB: + size = 2048; + break; + case I965_PGETBL_SIZE_1_5MB: + size = 1024 + 512; break; default: - dev_info(&agp_bridge->dev->dev, - "unknown page table size 0x%x, assuming 512KB\n", - (gmch_ctrl & I830_GMCH_GMS_MASK)); + dev_info(&intel_private.pcidev->dev, + "unknown page table size, assuming 512KB\n"); size = 512; } } else { @@ -1299,14 +1290,6 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp); pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, &temp2); - gtt_map_size = intel_i915_get_gtt_size(); - - intel_private.gtt = ioremap(temp2, gtt_map_size); - if (!intel_private.gtt) - return -ENOMEM; - - intel_private.gtt_total_size = gtt_map_size / 4; - temp &= 0xfff80000; intel_private.registers = ioremap(temp, 128 * 4096); @@ -1315,6 +1298,14 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) return -ENOMEM; } + gtt_map_size = intel_i915_get_gtt_size(); + + intel_private.gtt = ioremap(temp2, gtt_map_size); + if (!intel_private.gtt) + return -ENOMEM; + + intel_private.gtt_total_size = gtt_map_size / 4; + temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; global_cache_flush(); /* FIXME: ? */ -- cgit v1.2.3 From 852997dd63d9da05f9376c12c50a17da75f98c94 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 16 Sep 2010 17:50:31 +0200 Subject: sched: fix RCU lockdep splat from task_group() commit 6506cf6ce68d78a5470a8360c965dafe8e4b78e3 upstream. This addresses the following RCU lockdep splat: [0.051203] CPU0: AMD QEMU Virtual CPU version 0.12.4 stepping 03 [0.052999] lockdep: fixing up alternatives. [0.054105] [0.054106] =================================================== [0.054999] [ INFO: suspicious rcu_dereference_check() usage. ] [0.054999] --------------------------------------------------- [0.054999] kernel/sched.c:616 invoked rcu_dereference_check() without protection! [0.054999] [0.054999] other info that might help us debug this: [0.054999] [0.054999] [0.054999] rcu_scheduler_active = 1, debug_locks = 1 [0.054999] 3 locks held by swapper/1: [0.054999] #0: (cpu_add_remove_lock){+.+.+.}, at: [] cpu_up+0x42/0x6a [0.054999] #1: (cpu_hotplug.lock){+.+.+.}, at: [] cpu_hotplug_begin+0x2a/0x51 [0.054999] #2: (&rq->lock){-.-...}, at: [] init_idle+0x2f/0x113 [0.054999] [0.054999] stack backtrace: [0.054999] Pid: 1, comm: swapper Not tainted 2.6.35 #1 [0.054999] Call Trace: [0.054999] [] lockdep_rcu_dereference+0x9b/0xa3 [0.054999] [] task_group+0x7b/0x8a [0.054999] [] set_task_rq+0x13/0x40 [0.054999] [] init_idle+0xd2/0x113 [0.054999] [] fork_idle+0xb8/0xc7 [0.054999] [] ? mark_held_locks+0x4d/0x6b [0.054999] [] do_fork_idle+0x17/0x2b [0.054999] [] native_cpu_up+0x1c1/0x724 [0.054999] [] ? do_fork_idle+0x0/0x2b [0.054999] [] _cpu_up+0xac/0x127 [0.054999] [] cpu_up+0x55/0x6a [0.054999] [] kernel_init+0xe1/0x1ff [0.054999] [] kernel_thread_helper+0x4/0x10 [0.054999] [] ? restore_args+0x0/0x30 [0.054999] [] ? kernel_init+0x0/0x1ff [0.054999] [] ? kernel_thread_helper+0x0/0x10 [0.056074] Booting Node 0, Processors #1lockdep: fixing up alternatives. [0.130045] #2lockdep: fixing up alternatives. [0.203089] #3 Ok. [0.275286] Brought up 4 CPUs [0.276005] Total of 4 processors activated (16017.17 BogoMIPS). The cgroup_subsys_state structures referenced by idle tasks are never freed, because the idle tasks should be part of the root cgroup, which is not removable. The problem is that while we do in-fact hold rq->lock, the newly spawned idle thread's cpu is not yet set to the correct cpu so the lockdep check in task_group(): lockdep_is_held(&task_rq(p)->lock) will fail. But this is a chicken and egg problem. Setting the CPU's runqueue requires that the CPU's runqueue already be set. ;-) So insert an RCU read-side critical section to avoid the complaint. Signed-off-by: Peter Zijlstra Signed-off-by: Paul E. McKenney Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/sched.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/kernel/sched.c b/kernel/sched.c index 05b40f80e1d3..837f480d842c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -5157,7 +5157,19 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu) idle->se.exec_start = sched_clock(); cpumask_copy(&idle->cpus_allowed, cpumask_of(cpu)); + /* + * We're having a chicken and egg problem, even though we are + * holding rq->lock, the cpu isn't yet set to this cpu so the + * lockdep check in task_group() will fail. + * + * Similar case to sched_fork(). / Alternatively we could + * use task_rq_lock() here and obtain the other rq->lock. + * + * Silence PROVE_RCU + */ + rcu_read_lock(); __set_task_cpu(idle, cpu); + rcu_read_unlock(); rq->curr = rq->idle = idle; #if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW) -- cgit v1.2.3 From bcb8e33f1cccdeeffb9cccb729f31c11259fdae0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 1 Nov 2010 11:39:19 +0100 Subject: libata: fix NULL sdev dereference race in atapi_qc_complete() commit 2a5f07b5ec098edc69e05fdd2f35d3fbb1235723 upstream. SCSI commands may be issued between __scsi_add_device() and dev->sdev assignment, so it's unsafe for ata_qc_complete() to dereference dev->sdev->locked without checking whether it's NULL or not. Fix it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/ata/libata-scsi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index a54273d2c3c6..fb9e3eea020e 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2577,8 +2577,11 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) * * If door lock fails, always clear sdev->locked to * avoid this infinite loop. + * + * This may happen before SCSI scan is complete. Make + * sure qc->dev->sdev isn't NULL before dereferencing. */ - if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL) + if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL && qc->dev->sdev) qc->dev->sdev->locked = 0; qc->scsicmd->result = SAM_STAT_CHECK_CONDITION; -- cgit v1.2.3 From 9d5538131abcd941d16009c333c8b28b7ce5dc11 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Wed, 10 Nov 2010 11:03:21 +0100 Subject: PCI: fix size checks for mmap() on /proc/bus/pci files commit 3b519e4ea618b6943a82931630872907f9ac2c2b upstream. The checks for valid mmaps of PCI resources made through /proc/bus/pci files that were introduced in 9eff02e2042f96fb2aedd02e032eca1c5333d767 have several problems: 1. mmap() calls on /proc/bus/pci files are made with real file offsets > 0, whereas under /sys/bus/pci/devices, the start of the resource corresponds to offset 0. This may lead to false negatives in pci_mmap_fits(), which implicitly assumes the /sys/bus/pci/devices layout. 2. The loop in proc_bus_pci_mmap doesn't skip empty resouces. This leads to false positives, because pci_mmap_fits() doesn't treat empty resources correctly (the calculated size is 1 << (8*sizeof(resource_size_t)-PAGE_SHIFT) in this case!). 3. If a user maps resources with BAR > 0, pci_mmap_fits will emit bogus WARNINGS for the first resources that don't fit until the correct one is found. On many controllers the first 2-4 BARs are used, and the others are empty. In this case, an mmap attempt will first fail on the non-empty BARs (including the "right" BAR because of 1.) and emit bogus WARNINGS because of 3., and finally succeed on the first empty BAR because of 2. This is certainly not the intended behaviour. This patch addresses all 3 issues. Updated with an enum type for the additional parameter for pci_mmap_fits(). Signed-off-by: Martin Wilck Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/pci/pci-sysfs.c | 22 ++++++++++++++++------ drivers/pci/pci.h | 7 ++++++- drivers/pci/proc.c | 2 +- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index c9957f68ac9b..1e26afa2dc96 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -705,17 +705,21 @@ void pci_remove_legacy_files(struct pci_bus *b) #ifdef HAVE_PCI_MMAP -int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma) +int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma, + enum pci_mmap_api mmap_api) { - unsigned long nr, start, size; + unsigned long nr, start, size, pci_start; + if (pci_resource_len(pdev, resno) == 0) + return 0; nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; start = vma->vm_pgoff; size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1; - if (start < size && size - start >= nr) + pci_start = (mmap_api == PCI_MMAP_SYSFS) ? + pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0; + if (start >= pci_start && start < pci_start + size && + start + nr <= pci_start + size) return 1; - WARN(1, "process \"%s\" tried to map 0x%08lx-0x%08lx on %s BAR %d (size 0x%08lx)\n", - current->comm, start, start+nr, pci_name(pdev), resno, size); return 0; } @@ -745,8 +749,14 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, if (i >= PCI_ROM_RESOURCE) return -ENODEV; - if (!pci_mmap_fits(pdev, i, vma)) + if (!pci_mmap_fits(pdev, i, vma, PCI_MMAP_SYSFS)) { + WARN(1, "process \"%s\" tried to map 0x%08lx bytes " + "at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)\n", + current->comm, vma->vm_end-vma->vm_start, vma->vm_pgoff, + pci_name(pdev), i, + pci_resource_start(pdev, i), pci_resource_len(pdev, i)); return -EINVAL; + } /* pci_mmap_page_range() expects the same kind of entry as coming * from /proc/bus/pci/ which is a "user visible" value. If this is diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index f8077b3c8c8c..7c5c239fae46 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -13,8 +13,13 @@ extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev); extern void pci_cleanup_rom(struct pci_dev *dev); #ifdef HAVE_PCI_MMAP +enum pci_mmap_api { + PCI_MMAP_SYSFS, /* mmap on /sys/bus/pci/devices//resource */ + PCI_MMAP_PROCFS /* mmap on /proc/bus/pci/ */ +}; extern int pci_mmap_fits(struct pci_dev *pdev, int resno, - struct vm_area_struct *vma); + struct vm_area_struct *vmai, + enum pci_mmap_api mmap_api); #endif int pci_probe_reset_function(struct pci_dev *dev); diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 449e890267a2..64ac30b0da1e 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -260,7 +260,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) /* Make sure the caller is mapping a real resource for this device */ for (i = 0; i < PCI_ROM_RESOURCE; i++) { - if (pci_mmap_fits(dev, i, vma)) + if (pci_mmap_fits(dev, i, vma, PCI_MMAP_PROCFS)) break; } -- cgit v1.2.3 From e4027ab821c0db566c2db2fa0e82bffb76744e36 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Tue, 16 Nov 2010 09:13:41 -0800 Subject: PCI: fix offset check for sysfs mmapped files commit 8c05cd08a7504b855c265263e84af61aabafa329 upstream. I just loaded 2.6.37-rc2 on my machines, and I noticed that X no longer starts. Running an strace of the X server shows that it's doing this: open("/sys/bus/pci/devices/0000:07:00.0/resource0", O_RDWR) = 10 mmap(NULL, 16777216, PROT_READ|PROT_WRITE, MAP_SHARED, 10, 0) = -1 EINVAL (Invalid argument) This code seems to be asking for a shared read/write mapping of 16MB worth of BAR0 starting at file offset 0, and letting the kernel assign a starting address. Unfortunately, this -EINVAL causes X not to start. Looking into dmesg, there's a complaint like so: process "Xorg" tried to map 0x01000000 bytes at page 0x00000000 on 0000:07:00.0 BAR 0 (start 0x 96000000, size 0x 1000000) ...with the following code in pci_mmap_fits: pci_start = (mmap_api == PCI_MMAP_SYSFS) ? pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0; if (start >= pci_start && start < pci_start + size && start + nr <= pci_start + size) It looks like the logic here is set up such that when the mmap call comes via sysfs, the check in pci_mmap_fits wants vma->vm_pgoff to be between the resource's start and end address, and the end of the vma to be no farther than the end. However, the sysfs PCI resource files always start at offset zero, which means that this test always fails for programs that mmap the sysfs files. Given the comment in the original commit 3b519e4ea618b6943a82931630872907f9ac2c2b, I _think_ the old procfs files require that the file offset be equal to the resource's base address when mmapping. I think what we want here is for pci_start to be 0 when mmap_api == PCI_MMAP_PROCFS. The following patch makes that change, after which the Matrox and Mach64 X drivers work again. Acked-by: Martin Wilck Signed-off-by: Darrick J. Wong Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/pci/pci-sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 1e26afa2dc96..3d9f3eb45082 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -715,7 +715,7 @@ int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma, nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; start = vma->vm_pgoff; size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1; - pci_start = (mmap_api == PCI_MMAP_SYSFS) ? + pci_start = (mmap_api == PCI_MMAP_PROCFS) ? pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0; if (start >= pci_start && start < pci_start + size && start + nr <= pci_start + size) -- cgit v1.2.3 From b9c5ff8e4a33aa0746121ea828544a285df9f5b6 Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Thu, 11 Nov 2010 17:43:57 +0800 Subject: xHCI: fix wMaxPacketSize mask commit dc07c91b9b4067022210e68d914a6890a4d70622 upstream. USB2.0 spec 9.6.6 says: For all endpoints, bit 10..0 specify the maximum packet size(in bytes). So the wMaxPacketSize mask should be 0x7ff rather than 0x3ff. This patch should be queued for the stable tree. The bug in xhci_endpoint_init() was present as far back as 2.6.31, and the bug in xhci_get_max_esit_payload() was present when the function was introduced in 2.6.34. Reported-by: Sander Eikelenboom Signed-off-by: Andiry Xu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/xhci-mem.c | 4 ++-- drivers/usb/host/xhci.h | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 2eb658d26394..65d7cf3b4492 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1086,7 +1086,7 @@ static inline u32 xhci_get_max_esit_payload(struct xhci_hcd *xhci, if (udev->speed == USB_SPEED_SUPER) return ep->ss_ep_comp.wBytesPerInterval; - max_packet = ep->desc.wMaxPacketSize & 0x3ff; + max_packet = GET_MAX_PACKET(ep->desc.wMaxPacketSize); max_burst = (ep->desc.wMaxPacketSize & 0x1800) >> 11; /* A 0 in max burst means 1 transfer per ESIT */ return max_packet * (max_burst + 1); @@ -1165,7 +1165,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, /* Fall through */ case USB_SPEED_FULL: case USB_SPEED_LOW: - max_packet = ep->desc.wMaxPacketSize & 0x3ff; + max_packet = GET_MAX_PACKET(ep->desc.wMaxPacketSize); ep_ctx->ep_info2 |= MAX_PACKET(max_packet); break; default: diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 6c7e3430ec93..069876b6902b 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -614,6 +614,11 @@ struct xhci_ep_ctx { #define MAX_PACKET_MASK (0xffff << 16) #define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff) +/* Get max packet size from ep desc. Bit 10..0 specify the max packet size. + * USB2.0 spec 9.6.6. + */ +#define GET_MAX_PACKET(p) ((p) & 0x7ff) + /* tx_info bitmasks */ #define AVG_TRB_LENGTH_FOR_EP(p) ((p) & 0xffff) #define MAX_ESIT_PAYLOAD_FOR_EP(p) (((p) & 0xffff) << 16) -- cgit v1.2.3 From 60e2b701c5d6e82790e111c05df8a184b4eaa09e Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Wed, 17 Nov 2010 16:26:50 -0800 Subject: xhci: Fix reset-device and configure-endpoint commands commit 7a3783efffc7bc2e702d774e47fad5b8e37e9ad1 upstream. We have been having problems with the USB-IF Gold Tree tests when plugging and unplugging devices from the tree. I have seen that the reset-device and configure-endpoint commands, which are invoked from xhci_discover_or_reset_device() and xhci_configure_endpoint(), will sometimes time out. After much debugging, I determined that the commands themselves do not actually time out, but rather their completion events do not get delivered to the right place. This happens when the command ring has just wrapped around, and it's enqueue pointer is left pointing to the link TRB. xhci_discover_or_reset_device() and xhci_configure_endpoint() use the enqueue pointer directly as their command TRB pointer, without checking whether it's pointing to the link TRB. When the completion event arrives, if the command TRB is pointing to the link TRB, the check against the command ring dequeue pointer in handle_cmd_in_cmd_wait_list() fails, so the completion inside the command does not get signaled. The patch below fixes the timeout problem for me. This should be queued for the 2.6.35 and 2.6.36 stable trees. Signed-off-by: Paul Zimmerman Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/xhci.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 3998f72cd0c4..2ff4f6383da6 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1224,6 +1224,15 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, cmd_completion = command->completion; cmd_status = &command->status; command->command_trb = xhci->cmd_ring->enqueue; + + /* Enqueue pointer can be left pointing to the link TRB, + * we must handle that + */ + if ((command->command_trb->link.control & TRB_TYPE_BITMASK) + == TRB_TYPE(TRB_LINK)) + command->command_trb = + xhci->cmd_ring->enq_seg->next->trbs; + list_add_tail(&command->cmd_list, &virt_dev->cmd_list); } else { in_ctx = virt_dev->in_ctx; @@ -1933,6 +1942,15 @@ int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev) /* Attempt to submit the Reset Device command to the command ring */ spin_lock_irqsave(&xhci->lock, flags); reset_device_cmd->command_trb = xhci->cmd_ring->enqueue; + + /* Enqueue pointer can be left pointing to the link TRB, + * we must handle that + */ + if ((reset_device_cmd->command_trb->link.control & TRB_TYPE_BITMASK) + == TRB_TYPE(TRB_LINK)) + reset_device_cmd->command_trb = + xhci->cmd_ring->enq_seg->next->trbs; + list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list); ret = xhci_queue_reset_device(xhci, slot_id); if (ret) { -- cgit v1.2.3 From d52a93879e54fac8fb17f566f226c1060c7d1a84 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 26 Oct 2010 16:47:13 -0700 Subject: xhci: Setup array of USB 2.0 and USB 3.0 ports. commit da6699ce4a889c3795624ccdcfe7181cc89f18e8 upstream. An xHCI host controller contains USB 2.0 and USB 3.0 ports, which can occur in any order in the PORTSC registers. We cannot read the port speed bits in the PORTSC registers at init time to determine the port speed, since those bits are only valid when a USB device is plugged into the port. Instead, we read the "Supported Protocol Capability" registers in the xHC Extended Capabilities space. Those describe the protocol, port offset in the PORTSC registers, and port count. We use those registers to create two arrays of pointers to the PORTSC registers, one for USB 3.0 ports, and another for USB 2.0 ports. A third array keeps track of the port protocol major revision, and is indexed with the internal xHCI port number. This commit is a bit big, but it should be queued for stable because the "Don't let the USB core disable SuperSpeed ports" patch depends on it. There is no other way to determine which ports are SuperSpeed ports without this patch. Signed-off-by: Sarah Sharp Tested-by: Don Zickus Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/xhci-mem.c | 164 ++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/xhci.h | 27 ++++++++ 2 files changed, 191 insertions(+) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 65d7cf3b4492..c56afe77d9a2 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1457,6 +1457,13 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci->dcbaa = NULL; scratchpad_free(xhci); + + xhci->num_usb2_ports = 0; + xhci->num_usb3_ports = 0; + kfree(xhci->usb2_ports); + kfree(xhci->usb3_ports); + kfree(xhci->port_array); + xhci->page_size = 0; xhci->page_shift = 0; } @@ -1617,6 +1624,161 @@ static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci, gfp_t mem_flags) return 0; } +static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, + u32 __iomem *addr, u8 major_revision) +{ + u32 temp, port_offset, port_count; + int i; + + if (major_revision > 0x03) { + xhci_warn(xhci, "Ignoring unknown port speed, " + "Ext Cap %p, revision = 0x%x\n", + addr, major_revision); + /* Ignoring port protocol we can't understand. FIXME */ + return; + } + + /* Port offset and count in the third dword, see section 7.2 */ + temp = xhci_readl(xhci, addr + 2); + port_offset = XHCI_EXT_PORT_OFF(temp); + port_count = XHCI_EXT_PORT_COUNT(temp); + xhci_dbg(xhci, "Ext Cap %p, port offset = %u, " + "count = %u, revision = 0x%x\n", + addr, port_offset, port_count, major_revision); + /* Port count includes the current port offset */ + if (port_offset == 0 || (port_offset + port_count - 1) > num_ports) + /* WTF? "Valid values are ‘1’ to MaxPorts" */ + return; + port_offset--; + for (i = port_offset; i < (port_offset + port_count); i++) { + /* Duplicate entry. Ignore the port if the revisions differ. */ + if (xhci->port_array[i] != 0) { + xhci_warn(xhci, "Duplicate port entry, Ext Cap %p," + " port %u\n", addr, i); + xhci_warn(xhci, "Port was marked as USB %u, " + "duplicated as USB %u\n", + xhci->port_array[i], major_revision); + /* Only adjust the roothub port counts if we haven't + * found a similar duplicate. + */ + if (xhci->port_array[i] != major_revision && + xhci->port_array[i] != (u8) -1) { + if (xhci->port_array[i] == 0x03) + xhci->num_usb3_ports--; + else + xhci->num_usb2_ports--; + xhci->port_array[i] = (u8) -1; + } + /* FIXME: Should we disable the port? */ + } + xhci->port_array[i] = major_revision; + if (major_revision == 0x03) + xhci->num_usb3_ports++; + else + xhci->num_usb2_ports++; + } + /* FIXME: Should we disable ports not in the Extended Capabilities? */ +} + +/* + * Scan the Extended Capabilities for the "Supported Protocol Capabilities" that + * specify what speeds each port is supposed to be. We can't count on the port + * speed bits in the PORTSC register being correct until a device is connected, + * but we need to set up the two fake roothubs with the correct number of USB + * 3.0 and USB 2.0 ports at host controller initialization time. + */ +static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) +{ + u32 __iomem *addr; + u32 offset; + unsigned int num_ports; + int i, port_index; + + addr = &xhci->cap_regs->hcc_params; + offset = XHCI_HCC_EXT_CAPS(xhci_readl(xhci, addr)); + if (offset == 0) { + xhci_err(xhci, "No Extended Capability registers, " + "unable to set up roothub.\n"); + return -ENODEV; + } + + num_ports = HCS_MAX_PORTS(xhci->hcs_params1); + xhci->port_array = kzalloc(sizeof(*xhci->port_array)*num_ports, flags); + if (!xhci->port_array) + return -ENOMEM; + + /* + * For whatever reason, the first capability offset is from the + * capability register base, not from the HCCPARAMS register. + * See section 5.3.6 for offset calculation. + */ + addr = &xhci->cap_regs->hc_capbase + offset; + while (1) { + u32 cap_id; + + cap_id = xhci_readl(xhci, addr); + if (XHCI_EXT_CAPS_ID(cap_id) == XHCI_EXT_CAPS_PROTOCOL) + xhci_add_in_port(xhci, num_ports, addr, + (u8) XHCI_EXT_PORT_MAJOR(cap_id)); + offset = XHCI_EXT_CAPS_NEXT(cap_id); + if (!offset || (xhci->num_usb2_ports + xhci->num_usb3_ports) + == num_ports) + break; + /* + * Once you're into the Extended Capabilities, the offset is + * always relative to the register holding the offset. + */ + addr += offset; + } + + if (xhci->num_usb2_ports == 0 && xhci->num_usb3_ports == 0) { + xhci_warn(xhci, "No ports on the roothubs?\n"); + return -ENODEV; + } + xhci_dbg(xhci, "Found %u USB 2.0 ports and %u USB 3.0 ports.\n", + xhci->num_usb2_ports, xhci->num_usb3_ports); + /* + * Note we could have all USB 3.0 ports, or all USB 2.0 ports. + * Not sure how the USB core will handle a hub with no ports... + */ + if (xhci->num_usb2_ports) { + xhci->usb2_ports = kmalloc(sizeof(*xhci->usb2_ports)* + xhci->num_usb2_ports, flags); + if (!xhci->usb2_ports) + return -ENOMEM; + + port_index = 0; + for (i = 0; i < num_ports; i++) + if (xhci->port_array[i] != 0x03) { + xhci->usb2_ports[port_index] = + &xhci->op_regs->port_status_base + + NUM_PORT_REGS*i; + xhci_dbg(xhci, "USB 2.0 port at index %u, " + "addr = %p\n", i, + xhci->usb2_ports[port_index]); + port_index++; + } + } + if (xhci->num_usb3_ports) { + xhci->usb3_ports = kmalloc(sizeof(*xhci->usb3_ports)* + xhci->num_usb3_ports, flags); + if (!xhci->usb3_ports) + return -ENOMEM; + + port_index = 0; + for (i = 0; i < num_ports; i++) + if (xhci->port_array[i] == 0x03) { + xhci->usb3_ports[port_index] = + &xhci->op_regs->port_status_base + + NUM_PORT_REGS*i; + xhci_dbg(xhci, "USB 3.0 port at index %u, " + "addr = %p\n", i, + xhci->usb3_ports[port_index]); + port_index++; + } + } + return 0; +} int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) { @@ -1797,6 +1959,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) if (scratchpad_alloc(xhci, flags)) goto fail; + if (xhci_setup_port_arrays(xhci, flags)) + goto fail; return 0; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 069876b6902b..4a445bded9a6 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -447,6 +447,24 @@ struct xhci_doorbell_array { #define STREAM_ID_TO_DB(p) (((p) & 0xffff) << 16) +/** + * struct xhci_protocol_caps + * @revision: major revision, minor revision, capability ID, + * and next capability pointer. + * @name_string: Four ASCII characters to say which spec this xHC + * follows, typically "USB ". + * @port_info: Port offset, count, and protocol-defined information. + */ +struct xhci_protocol_caps { + u32 revision; + u32 name_string; + u32 port_info; +}; + +#define XHCI_EXT_PORT_MAJOR(x) (((x) >> 24) & 0xff) +#define XHCI_EXT_PORT_OFF(x) ((x) & 0xff) +#define XHCI_EXT_PORT_COUNT(x) (((x) >> 8) & 0xff) + /** * struct xhci_container_ctx * @type: Type of context. Used to calculated offsets to contained contexts. @@ -1187,6 +1205,15 @@ struct xhci_hcd { #define XHCI_LINK_TRB_QUIRK (1 << 0) #define XHCI_RESET_EP_QUIRK (1 << 1) #define XHCI_NEC_HOST (1 << 2) + + /* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */ + u8 *port_array; + /* Array of pointers to USB 3.0 PORTSC registers */ + u32 __iomem **usb3_ports; + unsigned int num_usb3_ports; + /* Array of pointers to USB 2.0 PORTSC registers */ + u32 __iomem **usb2_ports; + unsigned int num_usb2_ports; }; /* For testing purposes */ -- cgit v1.2.3 From 21f71d8817c6f240ab1c863d213bf5cd164aec73 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 16 Nov 2010 15:58:52 -0800 Subject: xhci: Don't let the USB core disable SuperSpeed ports. commit 6dd0a3a7e0793dbeae1b951f091025d8cf896cb4 upstream. Disabling SuperSpeed ports is a Very Bad Thing (TM). It disables SuperSpeed terminations, which means that devices will never connect at SuperSpeed on that port. For USB 2.0/1.1 ports, disabling the port meant that the USB core could always get a connect status change later. That's not true with USB 3.0 ports. Do not let the USB core disable SuperSpeed ports. We can't rely on the device speed in the port status registers, since that isn't valid until there's a USB device connected to the port. Instead, we use the port speed array that's created from the Extended Capabilities registers. Signed-off-by: Sarah Sharp Tested-by: Don Zickus Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/xhci-hub.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index a1a7a9795536..480936a870ce 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -132,6 +132,13 @@ static u32 xhci_port_state_to_neutral(u32 state) static void xhci_disable_port(struct xhci_hcd *xhci, u16 wIndex, u32 __iomem *addr, u32 port_status) { + /* Don't allow the USB core to disable SuperSpeed ports. */ + if (xhci->port_array[wIndex] == 0x03) { + xhci_dbg(xhci, "Ignoring request to disable " + "SuperSpeed port.\n"); + return; + } + /* Write 1 to disable the port */ xhci_writel(xhci, port_status | PORT_PE, addr); port_status = xhci_readl(xhci, addr); -- cgit v1.2.3 From 3e22d87b381cf915954772a8d4a9a7681d453b83 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Tue, 16 Nov 2010 11:51:32 +0100 Subject: USB: gadget: AT91: fix typo in atmel_usba_udc driver commit b48809518631880207796b4aab0fc39c2f036754 upstream. compile fix for bug introduced by 969affff547027) Signed-off-by: Josh Wu Cc: Jiri Kosina Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/gadget/atmel_usba_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 959f0624fe0d..2d19d88846ef 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -2016,7 +2016,7 @@ static int __init usba_udc_probe(struct platform_device *pdev) } } else { /* gpio_request fail so use -EINVAL for gpio_is_valid */ - ubc->vbus_pin = -EINVAL; + udc->vbus_pin = -EINVAL; } } -- cgit v1.2.3 From eafc2de6366f8b49aeeff5698a258f86ba5ffe75 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Wed, 27 Oct 2010 09:42:32 -0500 Subject: usb: musb: fix kernel oops when loading musb_hdrc module for the 2nd time commit b212091474a5f967979e62c5c24687ee4d0342d9 upstream. musb driver still may write MUSB_DEVCTL register after clock is disabled in musb_platform_exit, which may cause the kernel oops[1] when musb_hdrc module is loaded for the 2nd time. The patch fixes the kernel oops in this case. [1] kernel oops when loading musb_hdrc module for the 2nd time [ 93.380279] musb_hdrc: version 6.0, musb-dma, otg (peripheral+host), debug=5 [ 93.387847] bus: 'platform': add driver musb_hdrc [ 93.388153] bus: 'platform': driver_probe_device: matched device musb_hdrc with driver musb_hdrc [ 93.388183] bus: 'platform': really_probe: probing driver musb_hdrc with device musb_hdrc [ 93.405090] HS USB OTG: revision 0x33, sysconfig 0x2010, sysstatus 0x1, intrfsel 0x1, simenable 0x0 [ 93.405364] musb_hdrc: ConfigData=0xde (UTMI-8, dyn FIFOs, bulk combine, bulk split, HB-ISO Rx, HB-ISO Tx, SoftConn) [ 93.405395] musb_hdrc: MHDRC RTL version 1.400 [ 93.405426] musb_hdrc: setup fifo_mode 3 [ 93.405456] musb_hdrc: 7/31 max ep, 3648/16384 memory [ 93.405487] musb_core_init 1524: musb_hdrc: hw_ep 0shared, max 64 [ 93.405487] musb_core_init 1524: musb_hdrc: hw_ep 1tx, doublebuffer, max 512 [ 93.405517] musb_core_init 1533: musb_hdrc: hw_ep 1rx, doublebuffer, max 512 [ 93.405548] musb_core_init 1524: musb_hdrc: hw_ep 2tx, max 512 [ 93.405578] musb_core_init 1533: musb_hdrc: hw_ep 2rx, max 512 [ 93.405578] musb_core_init 1524: musb_hdrc: hw_ep 3shared, max 256 [ 93.405609] musb_core_init 1524: musb_hdrc: hw_ep 4shared, max 256 [ 93.405853] musb_platform_try_idle 133: b_idle inactive, for idle timer for 7 ms [ 93.405944] device: 'gadget': device_add [ 93.406921] PM: Adding info for No Bus:gadget [ 93.406951] musb_init_controller 2136: OTG mode, status 0, dev80 [ 93.407379] musb_do_idle 51: musb_do_idle: state=1 [ 93.408233] musb_hdrc musb_hdrc: USB OTG mode controller at fa0ab000 using DMA, IRQ 92 [ 93.416656] driver: 'musb_hdrc': driver_bound: bound to device 'musb_hdrc' [ 93.416687] bus: 'platform': really_probe: bound device musb_hdrc to driver musb_hdrc [ 124.486938] bus: 'platform': remove driver musb_hdrc [ 124.490509] twl4030_usb twl4030_usb: twl4030_phy_suspend [ 124.491424] device: 'gadget': device_unregister [ 124.491424] PM: Removing info for No Bus:gadget [ 124.495269] gadget: musb_gadget_release [ 124.498992] driver: 'musb_hdrc': driver_release [ 129.569366] musb_hdrc: version 6.0, musb-dma, otg (peripheral+host), debug=5 [ 129.576934] bus: 'platform': add driver musb_hdrc [ 129.577209] bus: 'platform': driver_probe_device: matched device musb_hdrc with driver musb_hdrc [ 129.577239] bus: 'platform': really_probe: probing driver musb_hdrc with device musb_hdrc [ 129.592651] twl4030_usb twl4030_usb: twl4030_phy_resume [ 129.592681] Unhandled fault: external abort on non-linefetch (0x1028) at 0xfa0ab404 [ 129.600830] Internal error: : 1028 [#1] [ 129.604858] last sysfs file: /sys/devices/platform/i2c_omap.3/i2c-3/i2c-dev/i2c-3/dev [ 129.613067] Modules linked in: musb_hdrc(+) [last unloaded: musb_hdrc] [ 129.619964] CPU: 0 Not tainted (2.6.36-next-20101021+ #372) [ 129.626281] PC is at musb_platform_init+0xb0/0x1c8 [musb_hdrc] [ 129.632415] LR is at mark_held_locks+0x64/0x94 [ 129.637084] pc : [] lr : [] psr: 20000013 [ 129.637084] sp : c6d5fcb0 ip : c6d5fc38 fp : c6d5fcd4 [ 129.649139] r10: c6e72180 r9 : fa0ab000 r8 : c05612e8 [ 129.654602] r7 : 0000005c r6 : c0559cc8 r5 : c6e72180 r4 : c0561548 [ 129.661468] r3 : 04d60047 r2 : fa0ab000 r1 : c07169d8 r0 : 00000000 [ 129.668304] Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user [ 129.675811] Control: 10c5387d Table: 86e4c019 DAC: 00000015 [ 129.681823] Process insmod (pid: 554, stack limit = 0xc6d5e2f0) [ 129.688049] Stack: (0xc6d5fcb0 to 0xc6d60000) [ 129.692626] fca0: fa0ab000 c0555c54 c6d5fcd4 c0561548 [ 129.701202] fcc0: 00000003 c05612e0 c6d5fe04 c6d5fcd8 bf03140c bf0320f4 c6d5fd9c c6d5fce8 [ 129.709808] fce0: c015cb94 c041448c c06d9d10 ffffffff c6d5fd14 c6d5fd00 c00adbec c6d5fd40 [ 129.718383] fd00: c015d478 c6d5fdb0 c6d5fd24 c00a9d18 c6d5e000 60000013 bf02a4ac c05612bc [ 129.726989] fd20: c0414fb4 c00a9cf0 c6d5fd54 c6d5fd38 c015bbdc c0244280 c6e8b7b0 c7929330 [ 129.735565] fd40: c6d5fdb0 c6d5fdb0 c6d5fd7c c6e7227c c015c010 c015bb90 c015c2ac c6d5fdb0 [ 129.744171] fd60: c7929330 c6d5fdb0 c7929330 c6e8b7b0 c6d5fd9c 00000000 c7929330 c6e8b7b0 [ 129.752746] fd80: c6d5fdb0 00000000 00000001 00000000 c6d5fde4 c6d5fda0 c015d478 c015cb74 [ 129.761322] fda0: c056138c 00000000 c6d5fdcc c6d5fdb8 c7929330 00000000 c056138c c05612e8 [ 129.769927] fdc0: 00000000 c05612f0 c0c5d62c c06f6e00 c73217c0 00000000 c6d5fdf4 c05612e8 [ 129.778503] fde0: c05612e8 bf02a2e4 c0c5d62c c06f6e00 c73217c0 00000000 c6d5fe14 c6d5fe08 [ 129.787109] fe00: c029a398 bf0311c8 c6d5fe4c c6d5fe18 c0299120 c029a384 c7919140 22222222 [ 129.795684] fe20: c6d5fe4c c05612e8 c056131c bf02a2e4 c0299278 c06f6e00 c73217c0 00000000 [ 129.804290] fe40: c6d5fe6c c6d5fe50 c0299314 c0299020 00000000 c6d5fe70 bf02a2e4 c0299278 [ 129.812866] fe60: c6d5fe94 c6d5fe70 c02987d4 c0299284 c7825060 c78c6618 00000000 bf02a2e4 [ 129.821441] fe80: c06e4c98 00000000 c6d5fea4 c6d5fe98 c0298ea4 c0298778 c6d5fedc c6d5fea8 [ 129.830047] fea0: c0297f84 c0298e8c bf02716c 000b9008 bf02a2e4 bf02a2d0 000b9008 bf02a2e4 [ 129.838623] fec0: 00000000 c06f6e00 bf031000 00000000 c6d5fefc c6d5fee0 c0299614 c0297ec0 [ 129.847229] fee0: bf02a2d0 000b9008 bf02a388 00000000 c6d5ff0c c6d5ff00 c029a868 c02995a8 [ 129.855804] ff00: c6d5ff24 c6d5ff10 c029a88c c029a818 0010281c 000b9008 c6d5ff34 c6d5ff28 [ 129.864410] ff20: bf03104c c029a878 c6d5ff7c c6d5ff38 c00463dc bf03100c 00000000 00000000 [ 129.872985] ff40: 00000000 0010281c 000b9008 bf02a388 00000000 0010281c 000b9008 bf02a388 [ 129.881591] ff60: 00000000 c00521c8 c6d5e000 00000000 c6d5ffa4 c6d5ff80 c00bb9b8 c00463ac [ 129.890167] ff80: c00adc88 c00ada68 00097e8e bebbfcf4 0010281c 00000080 00000000 c6d5ffa8 [ 129.898742] ffa0: c0052000 c00bb908 00097e8e bebbfcf4 402c9008 0010281c 000b9008 bebbfe5a [ 129.907348] ffc0: 00097e8e bebbfcf4 0010281c 00000080 00000014 bebbfcf4 bebbfe06 0000005b [ 129.915924] ffe0: bebbf9a0 bebbf990 0001a108 40263ec0 60000010 402c9008 011b0000 0000007c [ 129.924499] Backtrace: [ 129.927185] [] (musb_platform_init+0x0/0x1c8 [musb_hdrc]) from [] (musb_probe+0x250/0xf2c [musb_hdrc]) [ 129.938781] r6:c05612e0 r5:00000003 r4:c0561548 [ 129.943695] [] (musb_probe+0x0/0xf2c [musb_hdrc]) from [] (platform_drv_probe+0x20/0x24) [ 129.954040] [] (platform_drv_probe+0x0/0x24) from [] (driver_probe_device+0x10c/0x264) [ 129.964172] [] (driver_probe_device+0x0/0x264) from [] (__driver_attach+0x9c/0xa0) [ 129.973968] [] (__driver_attach+0x0/0xa0) from [] (bus_for_each_dev+0x68/0x94) [ 129.983367] r7:c0299278 r6:bf02a2e4 r5:c6d5fe70 r4:00000000 [ 129.989349] [] (bus_for_each_dev+0x0/0x94) from [] (driver_attach+0x24/0x28) [ 129.998565] r7:00000000 r6:c06e4c98 r5:bf02a2e4 r4:00000000 [ 130.004547] [] (driver_attach+0x0/0x28) from [] (bus_add_driver+0xd0/0x274) [ 130.013671] [] (bus_add_driver+0x0/0x274) from [] (driver_register+0x78/0x158) [ 130.023101] [] (driver_register+0x0/0x158) from [] (platform_driver_register+0x5c/0x60) [ 130.033325] r7:00000000 r6:bf02a388 r5:000b9008 r4:bf02a2d0 [ 130.039276] [] (platform_driver_register+0x0/0x60) from [] (platform_driver_probe+0x20/0xa8) [ 130.050018] [] (platform_driver_probe+0x0/0xa8) from [] (musb_init+0x4c/0x54 [musb_hdrc]) [ 130.060424] r5:000b9008 r4:0010281c [ 130.064239] [] (musb_init+0x0/0x54 [musb_hdrc]) from [] (do_one_initcall+0x3c/0x1c0) [ 130.074218] [] (do_one_initcall+0x0/0x1c0) from [] (sys_init_module+0xbc/0x1d0) [ 130.083709] [] (sys_init_module+0x0/0x1d0) from [] (ret_fast_syscall+0x0/0x3c) [ 130.093109] r7:00000080 r6:0010281c r5:bebbfcf4 r4:00097e8e [ 130.099090] Code: 0a000046 e3a01001 e12fff33 e59520e4 (e5923404) [ 130.105621] ---[ end trace 1d0bd69deb79164d ]--- Cc: Ajay Kumar Gupta Cc: Sergei Shtylyov Cc: Anand Gadiyar Signed-off-by: Ming Lei Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/musb/musb_core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index fbb768d2545b..6128e7c200ff 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2244,7 +2244,6 @@ static int __exit musb_remove(struct platform_device *pdev) #endif musb_writeb(musb->mregs, MUSB_DEVCTL, 0); musb_platform_exit(musb); - musb_writeb(musb->mregs, MUSB_DEVCTL, 0); musb_free(musb); iounmap(ctrl_base); -- cgit v1.2.3 From af39033bf6c0db7caea68b6fcd3e1d7735116007 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 3 Nov 2010 11:54:12 +0100 Subject: USB: ftdi_sio: add device IDs for Milkymist One JTAG/serial commit 7fea0f714ffb3f303d4b66933af2df2f5584c9bf upstream. Add the USB IDs for the Milkymist One FTDI-based JTAG/serial adapter (http://projects.qi-hardware.com/index.php/p/mmone-jtag-serial-cable/) to the ftdi_sio driver and disable the first serial channel (used as JTAG from userspace). Signed-off-by: Sebastien Bourdeauducq Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/ftdi_sio.c | 2 ++ drivers/usb/serial/ftdi_sio_ids.h | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index e5438e67eaf1..fe8f80854f4b 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -794,6 +794,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) }, + { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index cf1aea1b9ee7..c6a925e1073a 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1100,3 +1100,10 @@ #define FTDI_SCIENCESCOPE_LOGBOOKML_PID 0xFF18 #define FTDI_SCIENCESCOPE_LS_LOGBOOK_PID 0xFF1C #define FTDI_SCIENCESCOPE_HS_LOGBOOK_PID 0xFF1D + +/* + * Milkymist One JTAG/Serial + */ +#define QIHARDWARE_VID 0x20B7 +#define MILKYMISTONE_JTAGSERIAL_PID 0x0713 + -- cgit v1.2.3 From b588bc2a4733db29d1fe1a0fb0b9e61aa5de3199 Mon Sep 17 00:00:00 2001 From: ma rui Date: Mon, 1 Nov 2010 11:32:18 +0800 Subject: USB: option: fix when the driver is loaded incorrectly for some Huawei devices. commit 58c0d9d70109bd7e82bdb9517007311a48499960 upstream. When huawei datacard with PID 0x14AC is insterted into Linux system, the present kernel will load the "option" driver to all the interfaces. But actually, some interfaces run as other function and do not need "option" driver. In this path, we modify the id_tables, when the PID is 0x14ac ,VID is 0x12d1, Only when the interface's Class is 0xff,Subclass is 0xff, Pro is 0xff, it does need "option" driver. Signed-off-by: ma rui Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/option.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 1987e6d1542e..ba23c21759ca 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -492,7 +492,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */ -- cgit v1.2.3 From 1adcc1ce769c8edae42dc135c841c84874f17f7d Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Sat, 6 Nov 2010 17:41:35 +0300 Subject: usb: misc: sisusbvga: fix information leak to userland commit 5dc92cf1d0b4b0debbd2e333b83f9746c103533d upstream. Structure sisusb_info is copied to userland with "sisusb_reserved" field uninitialized. It leads to leaking of contents of kernel stack memory. Signed-off-by: Vasiliy Kulikov Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/misc/sisusbvga/sisusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index d25814c172b2..e33bff5b414f 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -3008,6 +3008,7 @@ sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) #else x.sisusb_conactive = 0; #endif + memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved)); if (copy_to_user((void __user *)arg, &x, sizeof(x))) retval = -EFAULT; -- cgit v1.2.3 From 5f5e68292004921ff329aa58d27023f5e10ac27a Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Sat, 6 Nov 2010 17:41:31 +0300 Subject: usb: misc: iowarrior: fix information leak to userland commit eca67aaeebd6e5d22b0d991af1dd0424dc703bfb upstream. Structure iowarrior_info is copied to userland with padding byted between "serial" and "revision" fields uninitialized. It leads to leaking of contents of kernel stack memory. Signed-off-by: Vasiliy Kulikov Acked-by: Kees Cook Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/misc/iowarrior.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 7dc9d3c69984..b47e694207a3 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -552,6 +552,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, /* needed for power consumption */ struct usb_config_descriptor *cfg_descriptor = &dev->udev->actconfig->desc; + memset(&info, 0, sizeof(info)); /* directly from the descriptor */ info.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); info.product = dev->product_id; -- cgit v1.2.3 From 08dfe568671b01bf3c19c97b0dd91ea3a863123b Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Sat, 6 Nov 2010 17:41:28 +0300 Subject: usb: core: fix information leak to userland commit 886ccd4520064408ce5876cfe00554ce52ecf4a7 upstream. Structure usbdevfs_connectinfo is copied to userland with padding byted after "slow" field uninitialized. It leads to leaking of contents of kernel stack memory. Signed-off-by: Vasiliy Kulikov Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/core/devio.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index c2f62a3993d2..da050245a5cb 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -965,10 +965,11 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg) static int proc_connectinfo(struct dev_state *ps, void __user *arg) { - struct usbdevfs_connectinfo ci; + struct usbdevfs_connectinfo ci = { + .devnum = ps->dev->devnum, + .slow = ps->dev->speed == USB_SPEED_LOW + }; - ci.devnum = ps->dev->devnum; - ci.slow = ps->dev->speed == USB_SPEED_LOW; if (copy_to_user(arg, &ci, sizeof(ci))) return -EFAULT; return 0; -- cgit v1.2.3 From 7135addd4bb65ec5bba2b9accf4c37df881851cd Mon Sep 17 00:00:00 2001 From: John Tapsell Date: Thu, 25 Mar 2010 13:30:45 +0000 Subject: Staging: rt2870: Add USB ID for Buffalo Airstation WLI-UC-GN commit 251d380034c6c34efe75ffb89d863558ba68ec6a upstream. BugLink: http://bugs.launchpad.net/bugs/441990 This was tested to successfully enable the hardware. Signed-off-by: John Tapsell Signed-off-by: Stefan Bader Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/rt2860/usb_main_dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c index 2e5a407da34a..5f15647ee78c 100644 --- a/drivers/staging/rt2860/usb_main_dev.c +++ b/drivers/staging/rt2860/usb_main_dev.c @@ -182,6 +182,7 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x2001, 0x3C09)}, /* D-Link */ {USB_DEVICE(0x2001, 0x3C0A)}, /* D-Link 3072 */ {USB_DEVICE(0x2019, 0xED14)}, /* Planex Communications, Inc. */ + {USB_DEVICE(0x0411, 0x015D)}, /* Buffalo Airstation WLI-UC-GN */ {} /* Terminating entry */ }; -- cgit v1.2.3 From 88472ed6fe60117b8801a68e8c3cfff5ff812835 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 16 Nov 2010 10:57:37 -0500 Subject: USB: EHCI: fix obscure race in ehci_endpoint_disable commit 02e2c51ba3e80acde600721ea784c3ef84da5ea1 upstream. This patch (as1435) fixes an obscure and unlikely race in ehci-hcd. When an async URB is unlinked, the corresponding QH is removed from the async list. If the QH's endpoint is then disabled while the URB is being given back, ehci_endpoint_disable() won't find the QH on the async list, causing it to believe that the QH has been lost. This will lead to a memory leak at best and quite possibly to an oops. The solution is to trust usbcore not to lose track of endpoints. If the QH isn't on the async list then it doesn't need to be taken off the list, but the driver should still wait for the QH to become IDLE before disabling it. In theory this fixes Bugzilla #20182. In fact the race is so rare that it's not possible to tell whether the bug is still present. However, adding delays and making other changes to force the race seems to show that the patch works. Signed-off-by: Alan Stern Reported-by: Stefan Richter Signed-off-by: Andi Kleen CC: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a3ef2a9d9dc2..b14be9cd6f79 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1009,10 +1009,11 @@ rescan: tmp && tmp != qh; tmp = tmp->qh_next.qh) continue; - /* periodic qh self-unlinks on empty */ - if (!tmp) - goto nogood; - unlink_async (ehci, qh); + /* periodic qh self-unlinks on empty, and a COMPLETING qh + * may already be unlinked. + */ + if (tmp) + unlink_async(ehci, qh); /* FALL THROUGH */ case QH_STATE_UNLINK: /* wait for hw to finish? */ case QH_STATE_UNLINK_WAIT: @@ -1029,7 +1030,6 @@ idle_timeout: } /* else FALL THROUGH */ default: -nogood: /* caller was supposed to have unlinked any requests; * that's not our job. just leak this memory. */ -- cgit v1.2.3 From b67a993c99765451994590ccc4083c2599f9de6a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 15 Nov 2010 11:17:52 -0800 Subject: USB: storage: sierra_ms: fix sysfs file attribute commit d9624e75f6ad94d8a0718c1fafa89186d271a78c upstream. A non-writable sysfs file shouldn't have writable attributes. Reported-by: Linus Torvalds Cc: Kevin Lloyd Cc: Matthew Dharm Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/storage/sierra_ms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/storage/sierra_ms.c b/drivers/usb/storage/sierra_ms.c index 57fc2f532cab..ceba512f84d0 100644 --- a/drivers/usb/storage/sierra_ms.c +++ b/drivers/usb/storage/sierra_ms.c @@ -121,7 +121,7 @@ static ssize_t show_truinst(struct device *dev, struct device_attribute *attr, } return result; } -static DEVICE_ATTR(truinst, S_IWUGO | S_IRUGO, show_truinst, NULL); +static DEVICE_ATTR(truinst, S_IRUGO, show_truinst, NULL); int sierra_ms_init(struct us_data *us) { -- cgit v1.2.3 From b0866f4e290b7a45d1e2e82ec32a45d1a83c1737 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 15 Nov 2010 11:11:45 -0800 Subject: USB: atm: ueagle-atm: fix up some permissions on the sysfs files commit e502ac5e1eca99d7dc3f12b2a6780ccbca674858 upstream. Some of the sysfs files had the incorrect permissions. Some didn't make sense at all (writable for a file that you could not write to?) Reported-by: Linus Torvalds Cc: Matthieu Castet Cc: Stanislaw Gruszka Cc: Damien Bergamini Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/atm/ueagle-atm.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index e213d3fa4920..51dc44da2f58 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -2291,7 +2291,7 @@ out: return ret; } -static DEVICE_ATTR(stat_status, S_IWUGO | S_IRUGO, read_status, reboot); +static DEVICE_ATTR(stat_status, S_IWUSR | S_IRUGO, read_status, reboot); static ssize_t read_human_status(struct device *dev, struct device_attribute *attr, char *buf) @@ -2354,8 +2354,7 @@ out: return ret; } -static DEVICE_ATTR(stat_human_status, S_IWUGO | S_IRUGO, - read_human_status, NULL); +static DEVICE_ATTR(stat_human_status, S_IRUGO, read_human_status, NULL); static ssize_t read_delin(struct device *dev, struct device_attribute *attr, char *buf) @@ -2387,7 +2386,7 @@ out: return ret; } -static DEVICE_ATTR(stat_delin, S_IWUGO | S_IRUGO, read_delin, NULL); +static DEVICE_ATTR(stat_delin, S_IRUGO, read_delin, NULL); #define UEA_ATTR(name, reset) \ \ -- cgit v1.2.3 From 727fbf5e5760a100ab7192aa68c1738b4706d86d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 15 Nov 2010 11:32:38 -0800 Subject: USB: misc: cypress_cy7c63: fix up some sysfs attribute permissions commit c990600d340641150f7270470a64bd99a5c0b225 upstream. They should not be writable by any user. Reported-by: Linus Torvalds Cc: Oliver Bock Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/misc/cypress_cy7c63.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c index 2f43c57743c9..9251773ecef4 100644 --- a/drivers/usb/misc/cypress_cy7c63.c +++ b/drivers/usb/misc/cypress_cy7c63.c @@ -196,11 +196,9 @@ static ssize_t get_port1_handler(struct device *dev, return read_port(dev, attr, buf, 1, CYPRESS_READ_PORT_ID1); } -static DEVICE_ATTR(port0, S_IWUGO | S_IRUGO, - get_port0_handler, set_port0_handler); +static DEVICE_ATTR(port0, S_IRUGO | S_IWUSR, get_port0_handler, set_port0_handler); -static DEVICE_ATTR(port1, S_IWUGO | S_IRUGO, - get_port1_handler, set_port1_handler); +static DEVICE_ATTR(port1, S_IRUGO | S_IWUSR, get_port1_handler, set_port1_handler); static int cypress_probe(struct usb_interface *interface, -- cgit v1.2.3 From f523d85f52859960e420928d812341de4e6e0054 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 15 Nov 2010 11:35:49 -0800 Subject: USB: misc: usbled: fix up some sysfs attribute permissions commit 48f115470e68d443436b76b22dad63ffbffd6b97 upstream. They should not be writable by any user. Reported-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/misc/usbled.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c index 63da2c3c838f..c96f51de1696 100644 --- a/drivers/usb/misc/usbled.c +++ b/drivers/usb/misc/usbled.c @@ -94,7 +94,7 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co change_color(led); \ return count; \ } \ -static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); +static DEVICE_ATTR(value, S_IRUGO | S_IWUSR, show_##value, set_##value); show_set(blue); show_set(red); show_set(green); -- cgit v1.2.3 From b3f4c19eafb1a74f2e2bdf6002745bb53014ce53 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 15 Nov 2010 11:34:26 -0800 Subject: USB: misc: trancevibrator: fix up a sysfs attribute permission commit d489a4b3926bad571d404ca6508f6744b9602776 upstream. It should not be writable by any user. Reported-by: Linus Torvalds Cc: Sam Hocevar Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/misc/trancevibrator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/misc/trancevibrator.c b/drivers/usb/misc/trancevibrator.c index d77aba46ae85..f63776a48e2a 100644 --- a/drivers/usb/misc/trancevibrator.c +++ b/drivers/usb/misc/trancevibrator.c @@ -86,7 +86,7 @@ static ssize_t set_speed(struct device *dev, struct device_attribute *attr, return count; } -static DEVICE_ATTR(speed, S_IWUGO | S_IRUGO, show_speed, set_speed); +static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR, show_speed, set_speed); static int tv_probe(struct usb_interface *interface, const struct usb_device_id *id) -- cgit v1.2.3 From 727c9b4d3b2958822d59376cde7ef47ea4942537 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 15 Nov 2010 11:36:44 -0800 Subject: USB: misc: usbsevseg: fix up some sysfs attribute permissions commit e24d7ace4e822debcb78386bf279c9aba4d7fbd1 upstream. They should not be writable by any user. Reported-by: Linus Torvalds Cc: Harrison Metzger Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/misc/usbsevseg.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/usb/misc/usbsevseg.c b/drivers/usb/misc/usbsevseg.c index de8ef945b536..417b8f207e8b 100644 --- a/drivers/usb/misc/usbsevseg.c +++ b/drivers/usb/misc/usbsevseg.c @@ -192,7 +192,7 @@ static ssize_t set_attr_##name(struct device *dev, \ \ return count; \ } \ -static DEVICE_ATTR(name, S_IWUGO | S_IRUGO, show_attr_##name, set_attr_##name); +static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_attr_##name, set_attr_##name); static ssize_t show_attr_text(struct device *dev, struct device_attribute *attr, char *buf) @@ -223,7 +223,7 @@ static ssize_t set_attr_text(struct device *dev, return count; } -static DEVICE_ATTR(text, S_IWUGO | S_IRUGO, show_attr_text, set_attr_text); +static DEVICE_ATTR(text, S_IRUGO | S_IWUSR, show_attr_text, set_attr_text); static ssize_t show_attr_decimals(struct device *dev, struct device_attribute *attr, char *buf) @@ -272,8 +272,7 @@ static ssize_t set_attr_decimals(struct device *dev, return count; } -static DEVICE_ATTR(decimals, S_IWUGO | S_IRUGO, - show_attr_decimals, set_attr_decimals); +static DEVICE_ATTR(decimals, S_IRUGO | S_IWUSR, show_attr_decimals, set_attr_decimals); static ssize_t show_attr_textmode(struct device *dev, struct device_attribute *attr, char *buf) @@ -319,8 +318,7 @@ static ssize_t set_attr_textmode(struct device *dev, return -EINVAL; } -static DEVICE_ATTR(textmode, S_IWUGO | S_IRUGO, - show_attr_textmode, set_attr_textmode); +static DEVICE_ATTR(textmode, S_IRUGO | S_IWUSR, show_attr_textmode, set_attr_textmode); MYDEV_ATTR_SIMPLE_UNSIGNED(powered, update_display_powered); -- cgit v1.2.3 From c1235a4015fe1885a2eb67184fe50d4693351f2b Mon Sep 17 00:00:00 2001 From: Michael Stuermer Date: Thu, 18 Nov 2010 00:45:43 +0100 Subject: USB: ftdi_sio: Add ID for RT Systems USB-29B radio cable commit 28942bb6a9dd4e2ed793675e515cfb8297ed355b upstream. Another variant of the RT Systems programming cable for ham radios. Signed-off-by: Michael Stuermer Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index fe8f80854f4b..91df9f62780c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -696,6 +696,7 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_SERIAL_VX7_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_CT29B_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) }, { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index c6a925e1073a..9d3019271955 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -721,6 +721,7 @@ */ #define RTSYSTEMS_VID 0x2100 /* Vendor ID */ #define RTSYSTEMS_SERIAL_VX7_PID 0x9e52 /* Serial converter for VX-7 Radios using FT232RL */ +#define RTSYSTEMS_CT29B_PID 0x9e54 /* CT29B Radio Cable */ /* * Bayer Ascensia Contour blood glucose meter USB-converter cable. -- cgit v1.2.3 From 6c2ad879feaf8bc3ac8a6b031437c59936b4646b Mon Sep 17 00:00:00 2001 From: Jacques Viviers Date: Wed, 24 Nov 2010 11:56:38 +0200 Subject: USB: serial: ftdi_sio: Vardaan USB RS422/485 converter PID added commit 6fdbad8021151a9e93af8159a6232c8f26415c09 upstream. Add the PID for the Vardaan Enterprises VEUSB422R3 USB to RS422/485 converter. It uses the same chip as the FTDI_8U232AM_PID 0x6001. This should also work with the stable branches for: 2.6.31, 2.6.32, 2.6.33, 2.6.34, 2.6.35, 2.6.36 Signed-off-by: Jacques Viviers Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 91df9f62780c..a10942825936 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -201,6 +201,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, { USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) }, + { USB_DEVICE(FTDI_VID, FTDI_VARDAAN_PID) }, { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) }, { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) }, { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 9d3019271955..393c37d36c30 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -114,6 +114,9 @@ /* Lenz LI-USB Computer Interface. */ #define FTDI_LENZ_LIUSB_PID 0xD780 +/* Vardaan Enterprises Serial Interface VEUSB422R3 */ +#define FTDI_VARDAAN_PID 0xF070 + /* * Xsens Technologies BV products (http://www.xsens.com). */ -- cgit v1.2.3 From c42fe729ad67abe81b2e79d48134db10c6a0466d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 29 Nov 2010 10:17:22 -0500 Subject: USB: fix autosuspend bug in usb-serial commit abf03184a31a3286fc0ab30f838ddee8ba9f9b7b upstream. This patch (as1437) fixes a bug in the usb-serial autosuspend handling. Since the usb-serial core now has autosuspend support, it must set the .supports_autosuspend member in every serial driver it registers. Otherwise the usb_autopm_get_interface() call won't work. This fixes Bugzilla #23012. Signed-off-by: Alan Stern Reported-by: Kevin Smith Reported-and-tested-by: Simon Gerber Reported-and-tested-by: Matteo Croce Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/usb-serial.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 941c2d409f85..8fadc13b7afd 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -52,6 +52,7 @@ static struct usb_driver usb_serial_driver = { .suspend = usb_serial_suspend, .resume = usb_serial_resume, .no_dynamic_id = 1, + .supports_autosuspend = 1, }; /* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead @@ -1344,6 +1345,8 @@ int usb_serial_register(struct usb_serial_driver *driver) return -ENODEV; fixup_generic(driver); + if (driver->usb_driver) + driver->usb_driver->supports_autosuspend = 1; if (!driver->description) driver->description = driver->driver.name; -- cgit v1.2.3 From e34d1f648f557f496649f35ca11663cad59e0cc2 Mon Sep 17 00:00:00 2001 From: Anupam Chanda Date: Sun, 21 Nov 2010 09:54:21 -0800 Subject: e1000: fix screaming IRQ commit ab08853fab2093e5c6f5de56827a4c93dce4b055 upstream. VMWare reports that the e1000 driver has a bug when bringing down the interface, such that interrupts are not disabled in the hardware but the driver stops reporting that it consumed the interrupt. The fix is to set the driver's "down" flag later in the routine, after all the timers and such have exited, preventing the interrupt handler from being called and exiting early without handling the interrupt. CC: Anupam Chanda Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/e1000/e1000_main.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index a2680bfbc7ad..a7f39ea2d7d9 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -31,7 +31,7 @@ char e1000_driver_name[] = "e1000"; static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; -#define DRV_VERSION "7.3.21-k6-NAPI" +#define DRV_VERSION "7.3.21-k8-NAPI" const char e1000_driver_version[] = DRV_VERSION; static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; @@ -483,9 +483,6 @@ void e1000_down(struct e1000_adapter *adapter) struct net_device *netdev = adapter->netdev; u32 rctl, tctl; - /* signal that we're down so the interrupt handler does not - * reschedule our watchdog timer */ - set_bit(__E1000_DOWN, &adapter->flags); /* disable receives in the hardware */ rctl = er32(RCTL); @@ -506,6 +503,13 @@ void e1000_down(struct e1000_adapter *adapter) e1000_irq_disable(adapter); + /* + * Setting DOWN must be after irq_disable to prevent + * a screaming interrupt. Setting DOWN also prevents + * timers and tasks from rescheduling. + */ + set_bit(__E1000_DOWN, &adapter->flags); + del_timer_sync(&adapter->tx_fifo_stall_timer); del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->phy_info_timer); -- cgit v1.2.3 From 1e8d602368391f61481052600a6174eb049582a9 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 22 Oct 2010 10:02:06 +0800 Subject: ACPI battery: support percentage battery remaining capacity commit 557d58687dcdee6bc00c1a8f1fd4e0eac8fefce9 upstream. According to the ACPI spec, some kinds of primary battery can report percentage battery remaining capacity directly to OS. In this case, it reports the LastFullChargedCapacity == 100, BatteryPresentRate = 0xFFFFFFFF, and BatteryRemaingCapacity a percentage value, which actually means RemainingBatteryPercentage. Now we found some battery follows this rule even if it's a rechargeable. https://bugzilla.kernel.org/show_bug.cgi?id=15979 Handle these batteries correctly in ACPI battery driver so that they won't break userspace. Signed-off-by: Zhang Rui Tested-by: Sitsofe Wheeler Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/acpi/battery.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index dc58402b0a17..68919e2e07dd 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -98,6 +98,7 @@ enum { * due to bad math. */ ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, + ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, }; struct acpi_battery { @@ -413,6 +414,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery) result = extract_package(battery, buffer.pointer, info_offsets, ARRAY_SIZE(info_offsets)); kfree(buffer.pointer); + if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) + battery->full_charge_capacity = battery->design_capacity; return result; } @@ -449,6 +452,10 @@ static int acpi_battery_get_state(struct acpi_battery *battery) battery->rate_now != -1) battery->rate_now = abs((s16)battery->rate_now); + if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) + && battery->capacity_now >= 0 && battery->capacity_now <= 100) + battery->capacity_now = (battery->capacity_now * + battery->full_charge_capacity) / 100; return result; } @@ -562,6 +569,33 @@ static void acpi_battery_quirks(struct acpi_battery *battery) } } +/* + * According to the ACPI spec, some kinds of primary batteries can + * report percentage battery remaining capacity directly to OS. + * In this case, it reports the Last Full Charged Capacity == 100 + * and BatteryPresentRate == 0xFFFFFFFF. + * + * Now we found some battery reports percentage remaining capacity + * even if it's rechargeable. + * https://bugzilla.kernel.org/show_bug.cgi?id=15979 + * + * Handle this correctly so that they won't break userspace. + */ +static void acpi_battery_quirks2(struct acpi_battery *battery) +{ + if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) + return ; + + if (battery->full_charge_capacity == 100 && + battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN && + battery->capacity_now >=0 && battery->capacity_now <= 100) { + set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags); + battery->full_charge_capacity = battery->design_capacity; + battery->capacity_now = (battery->capacity_now * + battery->full_charge_capacity) / 100; + } +} + static int acpi_battery_update(struct acpi_battery *battery) { int result, old_present = acpi_battery_present(battery); @@ -587,7 +621,9 @@ static int acpi_battery_update(struct acpi_battery *battery) if (!battery->bat.dev) sysfs_add_battery(battery); #endif - return acpi_battery_get_state(battery); + result = acpi_battery_get_state(battery); + acpi_battery_quirks2(battery); + return result; } /* -------------------------------------------------------------------------- -- cgit v1.2.3 From a499d3ff08c1c10821a2a1811fe8597d50a8de62 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 12 Oct 2010 09:09:37 +0800 Subject: acpi-cpufreq: fix a memleak when unloading driver commit dab5fff14df2cd16eb1ad4c02e83915e1063fece upstream. We didn't free per_cpu(acfreq_data, cpu)->freq_table when acpi_freq driver is unloaded. Resulting in the following messages in /sys/kernel/debug/kmemleak: unreferenced object 0xf6450e80 (size 64): comm "modprobe", pid 1066, jiffies 4294677317 (age 19290.453s) hex dump (first 32 bytes): 00 00 00 00 e8 a2 24 00 01 00 00 00 00 9f 24 00 ......$.......$. 02 00 00 00 00 6a 18 00 03 00 00 00 00 35 0c 00 .....j.......5.. backtrace: [] kmemleak_alloc+0x27/0x50 [] __kmalloc+0xcf/0x110 [] acpi_cpufreq_cpu_init+0x1ee/0x4e4 [acpi_cpufreq] [] cpufreq_add_dev+0x142/0x3a0 [] sysdev_driver_register+0x97/0x110 [] cpufreq_register_driver+0x86/0x140 [] 0xf9dad080 [] do_one_initcall+0x30/0x160 [] sys_init_module+0x99/0x1e0 [] sysenter_do_call+0x12/0x26 [] 0xffffffff https://bugzilla.kernel.org/show_bug.cgi?id=15807#c21 Tested-by: Toralf Forster Signed-off-by: Zhang Rui Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 1d3cddaa40ee..5384b0418428 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -704,6 +704,7 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy) per_cpu(acfreq_data, policy->cpu) = NULL; acpi_processor_unregister_performance(data->acpi_data, policy->cpu); + kfree(data->freq_table); kfree(data); } -- cgit v1.2.3 From 594574f0ba7ae9985662f9b0b8a9754c9da552c3 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sat, 13 Nov 2010 00:58:54 -0500 Subject: ACPI: debugfs custom_method open to non-root commit ed3aada1bf34c5a9e98af167f125f8a740fc726a upstream. Currently we have: --w--w--w-. 1 root root 0 2010-11-11 14:56 /sys/kernel/debug/acpi/custom_method which is just crazy. Change this to --w-------. Signed-off-by: Dave Jones Signed-off-by: Len Brown Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/acpi/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index 146135e7a6a1..469f04940cf2 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c @@ -258,7 +258,7 @@ static int acpi_debugfs_init(void) if (!acpi_dir) goto err; - cm_dentry = debugfs_create_file("custom_method", S_IWUGO, + cm_dentry = debugfs_create_file("custom_method", S_IWUSR, acpi_dir, NULL, &cm_fops); if (!cm_dentry) goto err; -- cgit v1.2.3 From db2d10eec9355faf29135e5cfccfb41b1e7e0b8f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 18 Sep 2010 10:11:09 -0700 Subject: PNPACPI: cope with invalid device IDs commit 420a0f66378c84b00b0e603e4d38210102dbe367 upstream. If primary ID (HID) is invalid try locating first valid ID on compatible ID list before giving up. This helps, for example, to recognize i8042 AUX port on Sony Vaio VPCZ1 which uses SNYSYN0003 as HID. Without the patch users are forced to boot with i8042.nopnp to make use of their touchpads. Tested-by: Jan-Hendrik Zab Signed-off-by: Dmitry Torokhov Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/pnp/pnpacpi/core.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index f7ff628b7d94..4a4041c3299e 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -28,7 +28,7 @@ #include "../base.h" #include "pnpacpi.h" -static int num = 0; +static int num; /* We need only to blacklist devices that have already an acpi driver that * can't use pnp layer. We don't need to blacklist device that are directly @@ -157,11 +157,24 @@ struct pnp_protocol pnpacpi_protocol = { }; EXPORT_SYMBOL(pnpacpi_protocol); +static char *pnpacpi_get_id(struct acpi_device *device) +{ + struct acpi_hardware_id *id; + + list_for_each_entry(id, &device->pnp.ids, list) { + if (ispnpidacpi(id->id)) + return id->id; + } + + return NULL; +} + static int __init pnpacpi_add_device(struct acpi_device *device) { acpi_handle temp = NULL; acpi_status status; struct pnp_dev *dev; + char *pnpid; struct acpi_hardware_id *id; /* @@ -169,11 +182,17 @@ static int __init pnpacpi_add_device(struct acpi_device *device) * driver should not be loaded. */ status = acpi_get_handle(device->handle, "_CRS", &temp); - if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) || - is_exclusive_device(device) || (!device->status.present)) + if (ACPI_FAILURE(status)) + return 0; + + pnpid = pnpacpi_get_id(device); + if (!pnpid) + return 0; + + if (is_exclusive_device(device) || !device->status.present) return 0; - dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device)); + dev = pnp_alloc_dev(&pnpacpi_protocol, num, pnpid); if (!dev) return -ENOMEM; @@ -204,7 +223,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) pnpacpi_parse_resource_option_data(dev); list_for_each_entry(id, &device->pnp.ids, list) { - if (!strcmp(id->id, acpi_device_hid(device))) + if (!strcmp(id->id, pnpid)) continue; if (!ispnpidacpi(id->id)) continue; -- cgit v1.2.3 From c526b926bacd31f398384c42c1950dc077c903b9 Mon Sep 17 00:00:00 2001 From: Dmitri Belimov Date: Tue, 26 Oct 2010 00:31:40 -0300 Subject: saa7134: Fix autodetect for Behold A7 and H7 TV cards commit 35bbe587d0959712b69540077c9e0fd27d3e6baf upstream. The entries for those cards are after the generic entries, so they don't work, in practice. Moving them to happen before the generic entres fix the issue. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/media/video/saa7134/saa7134-cards.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 07f6bb8ef9d9..f55e67a3a615 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -6630,6 +6630,18 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x107d, .subdevice = 0x6655, .driver_data = SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5ace, /* Beholder Intl. Ltd. */ + .subdevice = 0x7190, + .driver_data = SAA7134_BOARD_BEHOLD_H7, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5ace, /* Beholder Intl. Ltd. */ + .subdevice = 0x7090, + .driver_data = SAA7134_BOARD_BEHOLD_A7, }, { /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -6668,18 +6680,6 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, .driver_data = SAA7134_BOARD_UNKNOWN, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5ace, /* Beholder Intl. Ltd. */ - .subdevice = 0x7190, - .driver_data = SAA7134_BOARD_BEHOLD_H7, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5ace, /* Beholder Intl. Ltd. */ - .subdevice = 0x7090, - .driver_data = SAA7134_BOARD_BEHOLD_A7, },{ /* --- end of list --- */ } -- cgit v1.2.3 From 962b4a64f5210a4aaefd09c318e6dd05242df0ce Mon Sep 17 00:00:00 2001 From: Ken Sumrall Date: Wed, 24 Nov 2010 12:57:00 -0800 Subject: fuse: fix attributes after open(O_TRUNC) commit a0822c55779d9319939eac69f00bb729ea9d23da upstream. The attribute cache for a file was not being cleared when a file is opened with O_TRUNC. If the filesystem's open operation truncates the file ("atomic_o_trunc" feature flag is set) then the kernel should invalidate the cached st_mtime and st_ctime attributes. Also i_size should be explicitly be set to zero as it is used sometimes without refreshing the cache. Signed-off-by: Ken Sumrall Cc: Anfei Cc: "Anand V. Avati" Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/fuse/file.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index ada0adeb3bb5..fcd36797e6cb 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -134,6 +134,7 @@ EXPORT_SYMBOL_GPL(fuse_do_open); void fuse_finish_open(struct inode *inode, struct file *file) { struct fuse_file *ff = file->private_data; + struct fuse_conn *fc = get_fuse_conn(inode); if (ff->open_flags & FOPEN_DIRECT_IO) file->f_op = &fuse_direct_io_file_operations; @@ -141,6 +142,15 @@ void fuse_finish_open(struct inode *inode, struct file *file) invalidate_inode_pages2(inode->i_mapping); if (ff->open_flags & FOPEN_NONSEEKABLE) nonseekable_open(inode, file); + if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC)) { + struct fuse_inode *fi = get_fuse_inode(inode); + + spin_lock(&fc->lock); + fi->attr_version = ++fc->attr_version; + i_size_write(inode, 0); + spin_unlock(&fc->lock); + fuse_invalidate_attr(inode); + } } int fuse_open_common(struct inode *inode, struct file *file, bool isdir) -- cgit v1.2.3 From 6c615d59289dc9e2034647f0c912561d30bdb473 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Thu, 2 Dec 2010 14:31:17 -0800 Subject: cs5535-gpio: apply CS5536 errata workaround for GPIOs commit 853ff88324a248a9f5da6e110850223db353ec07 upstream. The AMD Geode CS5536 Companion Device Silicon Revision B1 Specification Update mentions the follow as issue #36: "Atomic write transactions to the atomic GPIO High Bank Feature Bit registers should only affect the bits selected [...]" "after Suspend, an atomic write transaction [...] will clear all non-selected bits of the accessed register." In other words, writing to the high bank for a single GPIO bit will clear every other GPIO bit (but only sometimes after a suspend). The workaround described is obvious and simple; do a read-modify-write. This patch does that, and documents why we're doing it. Signed-off-by: Andres Salomon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpio/cs5535-gpio.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c index e23c06893d19..599f6c9e0fbf 100644 --- a/drivers/gpio/cs5535-gpio.c +++ b/drivers/gpio/cs5535-gpio.c @@ -56,6 +56,18 @@ static struct cs5535_gpio_chip { * registers, see include/linux/cs5535.h. */ +static void errata_outl(u32 val, unsigned long addr) +{ + /* + * According to the CS5536 errata (#36), after suspend + * a write to the high bank GPIO register will clear all + * non-selected bits; the recommended workaround is a + * read-modify-write operation. + */ + val |= inl(addr); + outl(val, addr); +} + static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset, unsigned int reg) { @@ -64,7 +76,7 @@ static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset, outl(1 << offset, chip->base + reg); else /* high bank register */ - outl(1 << (offset - 16), chip->base + 0x80 + reg); + errata_outl(1 << (offset - 16), chip->base + 0x80 + reg); } void cs5535_gpio_set(unsigned offset, unsigned int reg) @@ -86,7 +98,7 @@ static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset, outl(1 << (offset + 16), chip->base + reg); else /* high bank register */ - outl(1 << offset, chip->base + 0x80 + reg); + errata_outl(1 << offset, chip->base + 0x80 + reg); } void cs5535_gpio_clear(unsigned offset, unsigned int reg) -- cgit v1.2.3 From fa21da1870e6626274c934722801914690b2dd55 Mon Sep 17 00:00:00 2001 From: Nelson Elhage Date: Thu, 2 Dec 2010 14:31:21 -0800 Subject: do_exit(): make sure that we run with get_fs() == USER_DS commit 33dd94ae1ccbfb7bf0fb6c692bc3d1c4269e6177 upstream. If a user manages to trigger an oops with fs set to KERNEL_DS, fs is not otherwise reset before do_exit(). do_exit may later (via mm_release in fork.c) do a put_user to a user-controlled address, potentially allowing a user to leverage an oops into a controlled write into kernel memory. This is only triggerable in the presence of another bug, but this potentially turns a lot of DoS bugs into privilege escalations, so it's worth fixing. I have proof-of-concept code which uses this bug along with CVE-2010-3849 to write a zero to an arbitrary kernel address, so I've tested that this is not theoretical. A more logical place to put this fix might be when we know an oops has occurred, before we call do_exit(), but that would involve changing every architecture, in multiple places. Let's just stick it in do_exit instead. [akpm@linux-foundation.org: update code comment] Signed-off-by: Nelson Elhage Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/exit.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel/exit.c b/kernel/exit.c index ac90425ce996..d1e6789064cf 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -900,6 +900,15 @@ NORET_TYPE void do_exit(long code) if (unlikely(!tsk->pid)) panic("Attempted to kill the idle task!"); + /* + * If do_exit is called because this processes oopsed, it's possible + * that get_fs() was left as KERNEL_DS, so reset it to USER_DS before + * continuing. Amongst other possible reasons, this is to prevent + * mm_release()->clear_child_tid() from writing to a user-controlled + * kernel address. + */ + set_fs(USER_DS); + tracehook_report_exit(&code); validate_creds_for_do_exit(tsk); -- cgit v1.2.3 From d061b20e5c1a0594a61aa2f2a789c703ac57a344 Mon Sep 17 00:00:00 2001 From: Oskar Schirmer Date: Wed, 10 Nov 2010 21:06:13 +0000 Subject: cifs: fix another memleak, in cifs_root_iget commit a7851ce73b9fdef53f251420e6883cf4f3766534 upstream. cifs_root_iget allocates full_path through cifs_build_path_to_root, but fails to kfree it upon cifs_get_inode_info* failure. Make all failure exit paths traverse clean up handling at the end of the function. Signed-off-by: Oskar Schirmer Signed-off-by: Andi Kleen Reviewed-by: Jesper Juhl Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/inode.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 6f0683c68952..b5dbf82762de 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -804,8 +804,10 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) rc = cifs_get_inode_info(&inode, full_path, NULL, sb, xid, NULL); - if (!inode) - return ERR_PTR(-ENOMEM); + if (!inode) { + inode = ERR_PTR(rc); + goto out; + } if (rc && cifs_sb->tcon->ipc) { cFYI(1, "ipc connection - fake read inode"); @@ -816,13 +818,11 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) inode->i_uid = cifs_sb->mnt_uid; inode->i_gid = cifs_sb->mnt_gid; } else if (rc) { - kfree(full_path); - _FreeXid(xid); iget_failed(inode); - return ERR_PTR(rc); + inode = ERR_PTR(rc); } - +out: kfree(full_path); /* can not call macro FreeXid here since in a void func * TODO: This is no longer true -- cgit v1.2.3 From 77caa21878730e393b25868930dbddf686e77f33 Mon Sep 17 00:00:00 2001 From: Will Newton Date: Wed, 24 Nov 2010 12:56:55 -0800 Subject: uml: disable winch irq before freeing handler data commit 69e83dad5207f8f03c9699e57e1febb114383cb8 upstream. Disable the winch irq early to make sure we don't take an interrupt part way through the freeing of the handler data, resulting in a crash on shutdown: winch_interrupt : read failed, errno = 9 fd 13 is losing SIGWINCH support ------------[ cut here ]------------ WARNING: at lib/list_debug.c:48 list_del+0xc6/0x100() list_del corruption, next is LIST_POISON1 (00100100) 082578c8: [<081fd77f>] dump_stack+0x22/0x24 082578e0: [<0807a18a>] warn_slowpath_common+0x5a/0x80 08257908: [<0807a23e>] warn_slowpath_fmt+0x2e/0x30 08257920: [<08172196>] list_del+0xc6/0x100 08257940: [<08060244>] free_winch+0x14/0x80 08257958: [<080606fb>] winch_interrupt+0xdb/0xe0 08257978: [<080a65b5>] handle_IRQ_event+0x35/0xe0 08257998: [<080a8717>] handle_edge_irq+0xb7/0x170 082579bc: [<08059bc4>] do_IRQ+0x34/0x50 082579d4: [<08059e1b>] sigio_handler+0x5b/0x80 082579ec: [<0806a374>] sig_handler_common+0x44/0xb0 08257a68: [<0806a538>] sig_handler+0x38/0x50 08257a78: [<0806a77c>] handle_signal+0x5c/0xa0 08257a9c: [<0806be28>] hard_handler+0x18/0x20 08257aac: [<00c14400>] 0xc14400 Signed-off-by: Will Newton Acked-by: WANG Cong Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/um/drivers/line.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 7f7338c90784..1664cce7b0ac 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -727,6 +727,9 @@ struct winch { static void free_winch(struct winch *winch, int free_irq_ok) { + if (free_irq_ok) + free_irq(WINCH_IRQ, winch); + list_del(&winch->list); if (winch->pid != -1) @@ -735,8 +738,6 @@ static void free_winch(struct winch *winch, int free_irq_ok) os_close_file(winch->fd); if (winch->stack != 0) free_stack(winch->stack, 0); - if (free_irq_ok) - free_irq(WINCH_IRQ, winch); kfree(winch); } -- cgit v1.2.3 From 7e8d53c0fad544ddb5f62bb6faf836ec04256608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 24 Nov 2010 12:57:14 -0800 Subject: backlight: grab ops_lock before testing bd->ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit d1d73578e053b981c3611e5a211534290d24a5eb upstream. According to the comment describing ops_lock in the definition of struct backlight_device and when comparing with other functions in backlight.c the mutex must be hold when checking ops to be non-NULL. Fixes a problem added by c835ee7f4154992e6 ("backlight: Add suspend/resume support to the backlight core") in Jan 2009. Signed-off-by: Uwe Kleine-König Acked-by: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/video/backlight/backlight.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index e207810bba3c..08703299ef61 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -197,12 +197,12 @@ static int backlight_suspend(struct device *dev, pm_message_t state) { struct backlight_device *bd = to_backlight_device(dev); - if (bd->ops->options & BL_CORE_SUSPENDRESUME) { - mutex_lock(&bd->ops_lock); + mutex_lock(&bd->ops_lock); + if (bd->ops && bd->ops->options & BL_CORE_SUSPENDRESUME) { bd->props.state |= BL_CORE_SUSPENDED; backlight_update_status(bd); - mutex_unlock(&bd->ops_lock); } + mutex_unlock(&bd->ops_lock); return 0; } @@ -211,12 +211,12 @@ static int backlight_resume(struct device *dev) { struct backlight_device *bd = to_backlight_device(dev); - if (bd->ops->options & BL_CORE_SUSPENDRESUME) { - mutex_lock(&bd->ops_lock); + mutex_lock(&bd->ops_lock); + if (bd->ops && bd->ops->options & BL_CORE_SUSPENDRESUME) { bd->props.state &= ~BL_CORE_SUSPENDED; backlight_update_status(bd); - mutex_unlock(&bd->ops_lock); } + mutex_unlock(&bd->ops_lock); return 0; } -- cgit v1.2.3 From a28c2bb7f58fad804d4673eb37b7c0436b945f15 Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Wed, 24 Nov 2010 12:56:54 -0800 Subject: nommu: yield CPU while disposing VM commit 04c3496152394d17e3bc2316f9731ee3e8a026bc upstream. Depending on processor speed, page size, and the amount of memory a process is allowed to amass, cleanup of a large VM may freeze the system for many seconds. This can result in a watchdog timeout. Make sure other tasks receive some service when cleaning up large VMs. Signed-off-by: Steven J. Magnani Cc: Greg Ungerer Signed-off-by: Andi Kleen Reviewed-by: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/nommu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/nommu.c b/mm/nommu.c index e48b38c521e4..3e1854887418 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -1673,6 +1673,7 @@ void exit_mmap(struct mm_struct *mm) mm->mmap = vma->vm_next; delete_vma_from_mm(vma); delete_vma(mm, vma); + cond_resched(); } kleave(""); -- cgit v1.2.3 From 1442b66f3af5b6ecfb7d70f21c5d062f7c108e0b Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 11 Nov 2010 21:18:43 +0100 Subject: x86: Ignore trap bits on single step exceptions commit 6c0aca288e726405b01dacb12cac556454d34b2a upstream. When a single step exception fires, the trap bits, used to signal hardware breakpoints, are in a random state. These trap bits might be set if another exception will follow, like a breakpoint in the next instruction, or a watchpoint in the previous one. Or there can be any junk there. So if we handle these trap bits during the single step exception, we are going to handle an exception twice, or we are going to handle junk. Just ignore them in this case. This fixes https://bugzilla.kernel.org/show_bug.cgi?id=21332 Reported-by: Michael Stefaniuc Signed-off-by: Frederic Weisbecker Cc: Rafael J. Wysocki Cc: Maciej Rutecki Cc: Alexandre Julliard Cc: Jason Wessel Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/kernel/hw_breakpoint.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c index a8f1b803d2fd..f3654702099a 100644 --- a/arch/x86/kernel/hw_breakpoint.c +++ b/arch/x86/kernel/hw_breakpoint.c @@ -421,6 +421,10 @@ static int __kprobes hw_breakpoint_handler(struct die_args *args) dr6_p = (unsigned long *)ERR_PTR(args->err); dr6 = *dr6_p; + /* If it's a single step, TRAP bits are random */ + if (dr6 & DR_STEP) + return NOTIFY_DONE; + /* Do an early return if no trap bits are set in DR6 */ if ((dr6 & DR_TRAP_BITS) == 0) return NOTIFY_DONE; -- cgit v1.2.3 From 79ec0bc0601b3c1bce4457361ec9d477b7982480 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 11 Nov 2010 17:32:25 +0100 Subject: mmc: fix rmmod race for hosts using card-detection polling commit d9bcbf343ec63e1104b5276195888ee06b4d086f upstream. MMC hosts that poll for card detection by defining the MMC_CAP_NEEDS_POLL flag have a race on rmmod, where the delayed work is cancelled without waiting for completed polling. To prevent this a _sync version of the work cancellation has to be used. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/mmc/core/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 2876c3d80284..365997e28f32 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1160,7 +1160,7 @@ void mmc_stop_host(struct mmc_host *host) if (host->caps & MMC_CAP_DISABLE) cancel_delayed_work(&host->disable); - cancel_delayed_work(&host->detect); + cancel_delayed_work_sync(&host->detect); mmc_flush_scheduled_work(); /* clear pm flags now and let card drivers set them as needed */ -- cgit v1.2.3 From 0b755ae07e1ff0b1c48ea286c301570d745aa0b7 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Tue, 23 Nov 2010 11:02:13 +0000 Subject: DECnet: don't leak uninitialized stack byte commit 3c6f27bf33052ea6ba9d82369fb460726fb779c0 upstream. A single uninitialized padding byte is leaked to userspace. Signed-off-by: Dan Rosenberg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/decnet/af_decnet.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index d6b93d19790f..cf38f52be4f7 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -1556,6 +1556,8 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char __us if (r_len > sizeof(struct linkinfo_dn)) r_len = sizeof(struct linkinfo_dn); + memset(&link, 0, sizeof(link)); + switch(sock->state) { case SS_CONNECTING: link.idn_linkstate = LL_CONNECTING; -- cgit v1.2.3 From 5f47c09a27902117ef908f5fb07cad300e427980 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Mon, 8 Nov 2010 21:29:07 +0200 Subject: perf_events: Fix perf_counter_mmap() hook in mprotect() commit 63bfd7384b119409685a17d5c58f0b56e5dc03da upstream. As pointed out by Linus, commit dab5855 ("perf_counter: Add mmap event hooks to mprotect()") is fundamentally wrong as mprotect_fixup() can free 'vma' due to merging. Fix the problem by moving perf_event_mmap() hook to mprotect_fixup(). Note: there's another successful return path from mprotect_fixup() if old flags equal to new flags. We don't, however, need to call perf_event_mmap() there because 'perf' already knows the VMA is executable. Reported-by: Dave Jones Signed-off-by: Andi Kleen Analyzed-by: Linus Torvalds Cc: Ingo Molnar Reviewed-by: Peter Zijlstra Signed-off-by: Pekka Enberg Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mprotect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/mprotect.c b/mm/mprotect.c index 2d1bf7cf8851..4c5133873097 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -211,6 +211,7 @@ success: mmu_notifier_invalidate_range_end(mm, start, end); vm_stat_account(mm, oldflags, vma->vm_file, -nrpages); vm_stat_account(mm, newflags, vma->vm_file, nrpages); + perf_event_mmap(vma); return 0; fail: @@ -299,7 +300,6 @@ SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len, error = mprotect_fixup(vma, &prev, nstart, tmp, newflags); if (error) goto out; - perf_event_mmap(vma); nstart = tmp; if (nstart < prev->vm_end) -- cgit v1.2.3 From c088a5f8722f305b4bbaa94cad32f1bfa882bc71 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 28 Oct 2010 11:45:22 +0100 Subject: ARM: 6464/2: fix spinlock recursion in adjust_pte() commit 4e54d93d3c9846ba1c2644ad06463dafa690d1b7 upstream. When running following code in a machine which has VIVT caches and USE_SPLIT_PTLOCKS is not defined: fd = open("/etc/passwd", O_RDONLY); addr = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd, 0); addr2 = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd, 0); v = *((int *)addr); we will hang in spinlock recursion in the page fault handler: BUG: spinlock recursion on CPU#0, mmap_test/717 lock: c5e295d8, .magic: dead4ead, .owner: mmap_test/717, .owner_cpu: 0 [] (unwind_backtrace+0x0/0xec) [] (do_raw_spin_lock+0x40/0x140) [] (update_mmu_cache+0x208/0x250) [] (__do_fault+0x320/0x3ec) [] (handle_mm_fault+0x2f0/0x6d8) [] (do_page_fault+0xdc/0x1cc) [] (do_DataAbort+0x34/0x94) This comes from the fact that when USE_SPLIT_PTLOCKS is not defined, the only lock protecting the page tables is mm->page_table_lock which is already locked before update_mmu_cache() is called. Signed-off-by: Mika Westerberg Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/arm/mm/fault-armv.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 9b906dec1ca1..56036ff04deb 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -65,6 +65,30 @@ static int do_adjust_pte(struct vm_area_struct *vma, unsigned long address, return ret; } +#if USE_SPLIT_PTLOCKS +/* + * If we are using split PTE locks, then we need to take the page + * lock here. Otherwise we are using shared mm->page_table_lock + * which is already locked, thus cannot take it. + */ +static inline void do_pte_lock(spinlock_t *ptl) +{ + /* + * Use nested version here to indicate that we are already + * holding one similar spinlock. + */ + spin_lock_nested(ptl, SINGLE_DEPTH_NESTING); +} + +static inline void do_pte_unlock(spinlock_t *ptl) +{ + spin_unlock(ptl); +} +#else /* !USE_SPLIT_PTLOCKS */ +static inline void do_pte_lock(spinlock_t *ptl) {} +static inline void do_pte_unlock(spinlock_t *ptl) {} +#endif /* USE_SPLIT_PTLOCKS */ + static int adjust_pte(struct vm_area_struct *vma, unsigned long address, unsigned long pfn) { @@ -89,11 +113,11 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address, */ ptl = pte_lockptr(vma->vm_mm, pmd); pte = pte_offset_map_nested(pmd, address); - spin_lock(ptl); + do_pte_lock(ptl); ret = do_adjust_pte(vma, address, pfn, pte); - spin_unlock(ptl); + do_pte_unlock(ptl); pte_unmap_nested(pte); return ret; -- cgit v1.2.3 From a683346b0f0625d3b29194fa86082235d1e858ce Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 19 Nov 2010 13:18:31 +0100 Subject: ARM: 6489/1: thumb2: fix incorrect optimisation in usracc commit 1142b71d85894dcff1466dd6c871ea3c89e0352c upstream. Commit 8b592783 added a Thumb-2 variant of usracc which, when it is called with \rept=2, calls usraccoff once with an offset of 0 and secondly with a hard-coded offset of 4 in order to avoid incrementing the pointer again. If \inc != 4 then we will store the data to the wrong offset from \ptr. Luckily, the only caller that passes \rept=2 to this function is __clear_user so we haven't been actively corrupting user data. This patch fixes usracc to pass \inc instead of #4 to usraccoff when it is called a second time. Reported-by: Tony Thompson Acked-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/arm/include/asm/assembler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 6e8f05c8a1c8..d7575554e407 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -215,7 +215,7 @@ @ Slightly optimised to avoid incrementing the pointer twice usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort .if \rept == 2 - usraccoff \instr, \reg, \ptr, \inc, 4, \cond, \abort + usraccoff \instr, \reg, \ptr, \inc, \inc, \cond, \abort .endif add\cond \ptr, #\rept * \inc -- cgit v1.2.3 From a678efd76c8bb4041d95973c32f7def1fc7c43bf Mon Sep 17 00:00:00 2001 From: James Jones Date: Wed, 24 Nov 2010 00:21:37 +0100 Subject: ARM: 6482/2: Fix find_next_zero_bit and related assembly commit 0e91ec0c06d2cd15071a6021c94840a50e6671aa upstream. The find_next_bit, find_first_bit, find_next_zero_bit and find_first_zero_bit functions were not properly clamping to the maxbit argument at the bit level. They were instead only checking maxbit at the byte level. To fix this, add a compare and a conditional move instruction to the end of the common bit-within-the- byte code used by all the functions and be sure not to clobber the maxbit argument before it is used. Reviewed-by: Nicolas Pitre Tested-by: Stephen Warren Signed-off-by: James Jones Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/arm/lib/findbit.S | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S index 1e4cbd4e7be9..64f6bc1a9132 100644 --- a/arch/arm/lib/findbit.S +++ b/arch/arm/lib/findbit.S @@ -174,8 +174,8 @@ ENDPROC(_find_next_bit_be) */ .L_found: #if __LINUX_ARM_ARCH__ >= 5 - rsb r1, r3, #0 - and r3, r3, r1 + rsb r0, r3, #0 + and r3, r3, r0 clz r3, r3 rsb r3, r3, #31 add r0, r2, r3 @@ -190,5 +190,7 @@ ENDPROC(_find_next_bit_be) addeq r2, r2, #1 mov r0, r2 #endif + cmp r1, r0 @ Clamp to maxbit + movlo r0, r1 mov pc, lr -- cgit v1.2.3 From a0e9e686dccb2a7625f78b1e6ab0f5487a99261d Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 24 Nov 2010 12:56:52 -0800 Subject: leds: fix bug with reading NAS SS4200 dmi code commit 50d431e8a15701b599c98afe2b464eb33c952477 upstream. While running randconfg with ktest.pl I stumbled upon this bug: BUG: unable to handle kernel NULL pointer dereference at 0000000000000003 IP: [] strstr+0x39/0x86 PGD 0 Oops: 0000 [#1] SMP last sysfs file: CPU 0 Modules linked in: Pid: 1, comm: swapper Not tainted 2.6.37-rc1-test+ #6 DG965MQ/ RIP: 0010:[] [] strstr+0x39/0x86 RSP: 0018:ffff8800797cbd80 EFLAGS: 00010213 RAX: 0000000000000000 RBX: 0000000000000003 RCX: ffffffffffffffff RDX: 0000000000000000 RSI: ffffffff82eb7ac9 RDI: 0000000000000003 RBP: ffff8800797cbda0 R08: ffff880000000003 R09: 0000000000030725 R10: ffff88007d294c00 R11: 0000000000014c00 R12: 0000000000000020 R13: ffffffff82eb7ac9 R14: ffffffffffffffff R15: ffffffff82eb7b08 FS: 0000000000000000(0000) GS:ffff88007d200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000003 CR3: 0000000002a1d000 CR4: 00000000000006f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process swapper (pid: 1, threadinfo ffff8800797ca000, task ffff8800797d0000) Stack: 00000000000000ba ffffffff82eb7ac9 ffffffff82eb7ab8 00000000000000ba ffff8800797cbdf0 ffffffff81e2050f ffff8800797cbdc0 00000000815f913b ffff8800797cbe00 ffffffff82eb7ab8 0000000000000000 0000000000000000 Call Trace: [] dmi_matches+0x117/0x154 [] dmi_check_system+0x3d/0x8d [] ? nas_gpio_init+0x0/0x2c8 [] nas_gpio_init+0x24/0x2c8 [] ? wm8350_led_init+0x0/0x20 [] ? nas_gpio_init+0x0/0x2c8 [] do_one_initcall+0xab/0x1b2 [] kernel_init+0x248/0x331 [] kernel_thread_helper+0x4/0x10 [] ? kernel_init+0x0/0x331 Found that the nas_led_whitelist dmi_system_id structure array had no NULL end delimiter, causing the dmi_check_system() loop to read an undefined entry. Signed-off-by: Steven Rostedt Acked-by: Dave Hansen Acked-by: Richard Purdie Acked-by: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/leds/leds-ss4200.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c index a688293abd0b..614ebebaaa28 100644 --- a/drivers/leds/leds-ss4200.c +++ b/drivers/leds/leds-ss4200.c @@ -102,6 +102,7 @@ static struct dmi_system_id __initdata nas_led_whitelist[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "1.00.00") } }, + {} }; /* -- cgit v1.2.3 From ee8ee3cb9f8fe7a51ef7d2bec8495a92d2a2d338 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Nov 2010 11:21:36 -0800 Subject: Staging: udlfb: fix up some sysfs attribute permissions commit cc9ca9dfddda46b1802d325891a69d7efdbe1f1e and cc9ca9dfddda46b1802d325891a69d7efdbe1f1e upstream merged together. They should not be writable by any user Reported-by: Linus Torvalds Cc: Bernie Thompson Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/udlfb/udlfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c index c7e061e5e04d..456cd5c95765 100644 --- a/drivers/staging/udlfb/udlfb.c +++ b/drivers/staging/udlfb/udlfb.c @@ -1143,7 +1143,7 @@ static struct device_attribute fb_device_attrs[] = { __ATTR_RO(metrics_bytes_sent), __ATTR_RO(metrics_cpu_kcycles_used), __ATTR_RO(metrics_misc), - __ATTR(metrics_reset, S_IWUGO, NULL, metrics_reset_store), + __ATTR(metrics_reset, S_IWUSR, NULL, metrics_reset_store), __ATTR_RW(use_defio), }; -- cgit v1.2.3 From 5a9af118fbe4756ac93b7f201da149810b847b12 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Nov 2010 11:19:53 -0800 Subject: Staging: iio: adis16220: fix up some sysfs attribute permissions commit 1d904e8950c86e670ace237eaea1d48cd81e94df upstream. They should not be writable by any user Reported-by: Linus Torvalds Cc: Jonathan Cameron Cc: Barry Song Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/iio/accel/adis16220_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index 6de439fd1675..083c36297cde 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -506,7 +506,7 @@ static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16220_write_reset, 0); #define IIO_DEV_ATTR_CAPTURE(_store) \ - IIO_DEVICE_ATTR(capture, S_IWUGO, NULL, _store, 0) + IIO_DEVICE_ATTR(capture, S_IRUSR, NULL, _store, 0) static IIO_DEV_ATTR_CAPTURE(adis16220_write_capture); -- cgit v1.2.3 From 7e9c5c7682a9c821919210b036b3d3779ad06d8f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 18 Nov 2010 11:21:04 -0800 Subject: Staging: iio: adis16220: fix up my fixup for some sysfs attribute permissions commit c9e51d9e4bee3da47623622884f4828e079a0581 upstream. They should be writable by root, not readable. Doh, stupid me with the wrong flags. Reported-by: Jonathan Cameron Acked-by: Jonathan Cameron Cc: Barry Song Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/iio/accel/adis16220_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index 083c36297cde..92bdb825843c 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -506,7 +506,7 @@ static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16220_write_reset, 0); #define IIO_DEV_ATTR_CAPTURE(_store) \ - IIO_DEVICE_ATTR(capture, S_IRUSR, NULL, _store, 0) + IIO_DEVICE_ATTR(capture, S_IWUSR, NULL, _store, 0) static IIO_DEV_ATTR_CAPTURE(adis16220_write_capture); -- cgit v1.2.3 From ac0d92d5f069c3db8796a0cc9c75ea7e6be5e4a8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Nov 2010 11:21:03 -0800 Subject: Staging: samsung-laptop: fix up some sysfs attribute permissions commit 90c05b97fdec8d2196e420d98f774bab731af7aa upstream. They should not be writable by any user Reported-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/samsung-laptop/samsung-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/samsung-laptop/samsung-laptop.c b/drivers/staging/samsung-laptop/samsung-laptop.c index eb44b60e1eb5..28700b498273 100644 --- a/drivers/staging/samsung-laptop/samsung-laptop.c +++ b/drivers/staging/samsung-laptop/samsung-laptop.c @@ -356,7 +356,7 @@ static ssize_t set_silent_state(struct device *dev, } return count; } -static DEVICE_ATTR(silent, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(silent, S_IRUSR | S_IRUGO, get_silent_state, set_silent_state); -- cgit v1.2.3 From 3193e96dd9c553125f93f6b02c3d6c23e5a5dd9a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 18 Nov 2010 11:21:04 -0800 Subject: Staging: samsung-laptop: fix up my fixup for some sysfs attribute permissions commit 4d7bc388b44e42a1feafa35e50eef4f24d6ca59d upstream. They should be writable by root, not readable. Doh, stupid me with the wrong flags. Reported-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/samsung-laptop/samsung-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/samsung-laptop/samsung-laptop.c b/drivers/staging/samsung-laptop/samsung-laptop.c index 28700b498273..ac2bf11e1119 100644 --- a/drivers/staging/samsung-laptop/samsung-laptop.c +++ b/drivers/staging/samsung-laptop/samsung-laptop.c @@ -356,7 +356,7 @@ static ssize_t set_silent_state(struct device *dev, } return count; } -static DEVICE_ATTR(silent, S_IRUSR | S_IRUGO, +static DEVICE_ATTR(silent, S_IWUSR | S_IRUGO, get_silent_state, set_silent_state); -- cgit v1.2.3 From b9ecedaf9df73f65d9b542ae9e394616dfd25d5d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Nov 2010 11:18:33 -0800 Subject: Staging: frontier: fix up some sysfs attribute permissions commit 3bad28ec006ad6ab2bca4e5103860b75391e3c9d and 2a767fda5d0d8dcff465724dfad6ee131489b3f2 upstream merged together. They should not be writable by any user Reported-by: Linus Torvalds Cc: David Taht Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/frontier/tranzport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/frontier/tranzport.c b/drivers/staging/frontier/tranzport.c index eed74f0fe0b6..f21a0e8d8d9b 100644 --- a/drivers/staging/frontier/tranzport.c +++ b/drivers/staging/frontier/tranzport.c @@ -204,7 +204,7 @@ static void usb_tranzport_abort_transfers(struct usb_tranzport *dev) t->value = temp; \ return count; \ } \ - static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); + static DEVICE_ATTR(value, S_IWUSR | S_IRUGO, show_##value, set_##value); show_int(enable); show_int(offline); -- cgit v1.2.3 From 76ff15489a634e27146f6d1ccb198b6cd1d4e35e Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 13 Nov 2010 13:01:56 -0600 Subject: staging: rtl8187se: Change panic to warn when RF switch turned off commit f36d83a8cb7224f45fdfa1129a616dff56479a09 upstream. This driver issues a kernel panic over conditions that do not justify such drastic action. Change these to log entries with a stack dump. This patch fixes the system crash reported in https://bugs.launchpad.net/ubuntu/+source/linux/+bug/674285. Signed-off-by: Larry Finger Signed-off-by: Andi Kleen Reported-and-Tested-by: Robie Basik Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/r8185b_init.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c index a0ece1fd64a5..e7e8745c9478 100644 --- a/drivers/staging/rtl8187se/r8185b_init.c +++ b/drivers/staging/rtl8187se/r8185b_init.c @@ -268,8 +268,12 @@ HwHSSIThreeWire( } udelay(10); } - if (TryCnt == TC_3W_POLL_MAX_TRY_CNT) - panic("HwThreeWire(): CmdReg: %#X RE|WE bits are not clear!!\n", u1bTmp); + if (TryCnt == TC_3W_POLL_MAX_TRY_CNT) { + printk(KERN_ERR "rtl8187se: HwThreeWire(): CmdReg:" + " %#X RE|WE bits are not clear!!\n", u1bTmp); + dump_stack(); + return 0; + } // RTL8187S HSSI Read/Write Function u1bTmp = read_nic_byte(dev, RF_SW_CONFIG); @@ -309,13 +313,23 @@ HwHSSIThreeWire( int idx; int ByteCnt = nDataBufBitCnt / 8; //printk("%d\n",nDataBufBitCnt); - if ((nDataBufBitCnt % 8) != 0) - panic("HwThreeWire(): nDataBufBitCnt(%d) should be multiple of 8!!!\n", - nDataBufBitCnt); + if ((nDataBufBitCnt % 8) != 0) { + printk(KERN_ERR "rtl8187se: " + "HwThreeWire(): nDataBufBitCnt(%d)" + " should be multiple of 8!!!\n", + nDataBufBitCnt); + dump_stack(); + nDataBufBitCnt += 8; + nDataBufBitCnt &= ~7; + } - if (nDataBufBitCnt > 64) - panic("HwThreeWire(): nDataBufBitCnt(%d) should <= 64!!!\n", - nDataBufBitCnt); + if (nDataBufBitCnt > 64) { + printk(KERN_ERR "rtl8187se: HwThreeWire():" + " nDataBufBitCnt(%d) should <= 64!!!\n", + nDataBufBitCnt); + dump_stack(); + nDataBufBitCnt = 64; + } for(idx = 0; idx < ByteCnt; idx++) { -- cgit v1.2.3 From c044cc9988cd29246c6d6781068c710817dd2f29 Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Mon, 22 Nov 2010 12:34:49 +0100 Subject: Staging: batman-adv: ensure that eth_type_trans gets linear memory commit b6faaae1a15a352d68b3e3cd8b840e56709820bf upstream. eth_type_trans tries to pull data with the length of the ethernet header from the skb. We only ensured that enough data for the first ethernet header and the batman header is available in non-paged memory of the skb and not for the ethernet after the batman header. eth_type_trans would fail sometimes with drivers which don't ensure that all there data is perfectly linearised. The failure was noticed through a kernel bug Oops generated by the skb_pull inside eth_type_trans. Reported-by: Rafal Lesniak Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/batman-adv/soft-interface.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c index 51c40b77c8d7..0ae6c03612a9 100644 --- a/drivers/staging/batman-adv/soft-interface.c +++ b/drivers/staging/batman-adv/soft-interface.c @@ -295,6 +295,10 @@ void interface_rx(struct sk_buff *skb, int hdr_size) skb_pull_rcsum(skb, hdr_size); /* skb_set_mac_header(skb, -sizeof(struct ethhdr));*/ + if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) { + kfree_skb(skb); + return; + } skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); -- cgit v1.2.3 From bb25ed06260128cf99a46950cc1b0b131e9c9477 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 24 Nov 2010 10:05:55 +0100 Subject: perf: Fix inherit vs. context rotation bug commit dddd3379a619a4cb8247bfd3c94ca9ae3797aa2e upstream. It was found that sometimes children of tasks with inherited events had one extra event. Eventually it turned out to be due to the list rotation no being exclusive with the list iteration in the inheritance code. Cure this by temporarily disabling the rotation while we inherit the events. Signed-off-by: Thomas Gleixner Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- include/linux/perf_event.h | 1 + kernel/perf_event.c | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 5d0266d94985..bfacc8e269b1 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -764,6 +764,7 @@ struct perf_event_context { int nr_active; int is_active; int nr_stat; + int rotate_disable; atomic_t refcount; struct task_struct *task; diff --git a/kernel/perf_event.c b/kernel/perf_event.c index ac869dc78965..d1a6c04d8399 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -1609,8 +1609,12 @@ static void rotate_ctx(struct perf_event_context *ctx) { raw_spin_lock(&ctx->lock); - /* Rotate the first entry last of non-pinned groups */ - list_rotate_left(&ctx->flexible_groups); + /* + * Rotate the first entry last of non-pinned groups. Rotation might be + * disabled by the inheritance code. + */ + if (!ctx->rotate_disable) + list_rotate_left(&ctx->flexible_groups); raw_spin_unlock(&ctx->lock); } @@ -5596,6 +5600,7 @@ int perf_event_init_task(struct task_struct *child) struct perf_event *event; struct task_struct *parent = current; int inherited_all = 1; + unsigned long flags; int ret = 0; child->perf_event_ctxp = NULL; @@ -5636,6 +5641,15 @@ int perf_event_init_task(struct task_struct *child) break; } + /* + * We can't hold ctx->lock when iterating the ->flexible_group list due + * to allocations, but we need to prevent rotation because + * rotate_ctx() will change the list from interrupt context. + */ + raw_spin_lock_irqsave(&parent_ctx->lock, flags); + parent_ctx->rotate_disable = 1; + raw_spin_unlock_irqrestore(&parent_ctx->lock, flags); + list_for_each_entry(event, &parent_ctx->flexible_groups, group_entry) { ret = inherit_task_group(event, parent, parent_ctx, child, &inherited_all); @@ -5643,6 +5657,10 @@ int perf_event_init_task(struct task_struct *child) break; } + raw_spin_lock_irqsave(&parent_ctx->lock, flags); + parent_ctx->rotate_disable = 0; + raw_spin_unlock_irqrestore(&parent_ctx->lock, flags); + child_ctx = child->perf_event_ctxp; if (child_ctx && inherited_all) { -- cgit v1.2.3 From a8e8a6d0bca8893c544500e49cf824fded926a17 Mon Sep 17 00:00:00 2001 From: Marcelo Roberto Jimenez Date: Mon, 18 Oct 2010 22:38:08 +0100 Subject: ARM: 6456/1: Fix for building DEBUG with sa11xx_base.c as a module. commit b9f515e3e3861abbaa093359f7c6f31283695228 upstream. This patch fixes a compilation issue when compiling PCMCIA SA1100 support as a module with PCMCIA_DEBUG enabled. The symbol soc_pcmcia_debug was not beeing exported. ARM: pcmcia: Fix for building DEBUG with sa11xx_base.c as a module. This patch fixes a compilation issue when compiling PCMCIA SA1100 support as a module with PCMCIA_DEBUG enabled. The symbol soc_pcmcia_debug was not beeing exported. Signed-off-by: Marcelo Roberto Jimenez Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/pcmcia/soc_common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index 6f1a86b43c60..fd4c25ac18ec 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c @@ -65,6 +65,7 @@ void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func, va_end(args); } } +EXPORT_SYMBOL(soc_pcmcia_debug); #endif -- cgit v1.2.3 From f0ad38dade9e69ffefc37734b37e3bd93654a00f Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 3 Dec 2010 22:57:45 +0100 Subject: PM / Hibernate: Fix memory corruption related to swap commit c9e664f1fdf34aa8cede047b206deaa8f1945af0 upstream. There is a problem that swap pages allocated before the creation of a hibernation image can be released and used for storing the contents of different memory pages while the image is being saved. Since the kernel stored in the image doesn't know of that, it causes memory corruption to occur after resume from hibernation, especially on systems with relatively small RAM that need to swap often. This issue can be addressed by keeping the GFP_IOFS bits clear in gfp_allowed_mask during the entire hibernation, including the saving of the image, until the system is finally turned off or the hibernation is aborted. Unfortunately, for this purpose it's necessary to rework the way in which the hibernate and suspend code manipulates gfp_allowed_mask. This change is based on an earlier patch from Hugh Dickins. Signed-off-by: Rafael J. Wysocki Reported-by: Ondrej Zary Acked-by: Hugh Dickins Signed-off-by: Andi Kleen Reviewed-by: KAMEZAWA Hiroyuki Signed-off-by: Greg Kroah-Hartman --- include/linux/gfp.h | 4 ++-- kernel/power/hibernate.c | 22 ++++++++++++---------- kernel/power/suspend.c | 5 ++--- kernel/power/user.c | 2 ++ mm/page_alloc.c | 19 ++++++++++++------- 5 files changed, 30 insertions(+), 22 deletions(-) diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 975609cb8548..81483c20735f 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -339,7 +339,7 @@ void drain_local_pages(void *dummy); extern gfp_t gfp_allowed_mask; -extern void set_gfp_allowed_mask(gfp_t mask); -extern gfp_t clear_gfp_allowed_mask(gfp_t mask); +extern void pm_restrict_gfp_mask(void); +extern void pm_restore_gfp_mask(void); #endif /* __LINUX_GFP_H */ diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index aa9e916da4d5..684463e7e263 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -324,7 +324,6 @@ static int create_image(int platform_mode) int hibernation_snapshot(int platform_mode) { int error; - gfp_t saved_mask; error = platform_begin(platform_mode); if (error) @@ -336,7 +335,7 @@ int hibernation_snapshot(int platform_mode) goto Close; suspend_console(); - saved_mask = clear_gfp_allowed_mask(GFP_IOFS); + pm_restrict_gfp_mask(); error = dpm_suspend_start(PMSG_FREEZE); if (error) goto Recover_platform; @@ -345,7 +344,10 @@ int hibernation_snapshot(int platform_mode) goto Recover_platform; error = create_image(platform_mode); - /* Control returns here after successful restore */ + /* + * Control returns here (1) after the image has been created or the + * image creation has failed and (2) after a successful restore. + */ Resume_devices: /* We may need to release the preallocated image pages here. */ @@ -354,7 +356,10 @@ int hibernation_snapshot(int platform_mode) dpm_resume_end(in_suspend ? (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); - set_gfp_allowed_mask(saved_mask); + + if (error || !in_suspend) + pm_restore_gfp_mask(); + resume_console(); Close: platform_end(platform_mode); @@ -449,17 +454,16 @@ static int resume_target_kernel(bool platform_mode) int hibernation_restore(int platform_mode) { int error; - gfp_t saved_mask; pm_prepare_console(); suspend_console(); - saved_mask = clear_gfp_allowed_mask(GFP_IOFS); + pm_restrict_gfp_mask(); error = dpm_suspend_start(PMSG_QUIESCE); if (!error) { error = resume_target_kernel(platform_mode); dpm_resume_end(PMSG_RECOVER); } - set_gfp_allowed_mask(saved_mask); + pm_restore_gfp_mask(); resume_console(); pm_restore_console(); return error; @@ -473,7 +477,6 @@ int hibernation_restore(int platform_mode) int hibernation_platform_enter(void) { int error; - gfp_t saved_mask; if (!hibernation_ops) return -ENOSYS; @@ -489,7 +492,6 @@ int hibernation_platform_enter(void) entering_platform_hibernation = true; suspend_console(); - saved_mask = clear_gfp_allowed_mask(GFP_IOFS); error = dpm_suspend_start(PMSG_HIBERNATE); if (error) { if (hibernation_ops->recover) @@ -527,7 +529,6 @@ int hibernation_platform_enter(void) Resume_devices: entering_platform_hibernation = false; dpm_resume_end(PMSG_RESTORE); - set_gfp_allowed_mask(saved_mask); resume_console(); Close: @@ -635,6 +636,7 @@ int hibernate(void) swsusp_free(); if (!error) power_down(); + pm_restore_gfp_mask(); } else { pr_debug("PM: Image restored successfully.\n"); } diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index f37cb7dd4402..b0f28dddc04e 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -196,7 +196,6 @@ static int suspend_enter(suspend_state_t state) int suspend_devices_and_enter(suspend_state_t state) { int error; - gfp_t saved_mask; if (!suspend_ops) return -ENOSYS; @@ -207,7 +206,7 @@ int suspend_devices_and_enter(suspend_state_t state) goto Close; } suspend_console(); - saved_mask = clear_gfp_allowed_mask(GFP_IOFS); + pm_restrict_gfp_mask(); suspend_test_start(); error = dpm_suspend_start(PMSG_SUSPEND); if (error) { @@ -224,7 +223,7 @@ int suspend_devices_and_enter(suspend_state_t state) suspend_test_start(); dpm_resume_end(PMSG_RESUME); suspend_test_finish("resume devices"); - set_gfp_allowed_mask(saved_mask); + pm_restore_gfp_mask(); resume_console(); Close: if (suspend_ops->end) diff --git a/kernel/power/user.c b/kernel/power/user.c index e819e17877ca..1b2ea31e6bd8 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -263,6 +263,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, case SNAPSHOT_UNFREEZE: if (!data->frozen || data->ready) break; + pm_restore_gfp_mask(); thaw_processes(); usermodehelper_enable(); data->frozen = 0; @@ -275,6 +276,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, error = -EPERM; break; } + pm_restore_gfp_mask(); error = hibernation_snapshot(data->platform_support); if (!error) error = put_user(in_suspend, (int __user *)arg); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 3390da65f161..2b085d51411c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -103,19 +103,24 @@ gfp_t gfp_allowed_mask __read_mostly = GFP_BOOT_MASK; * only be modified with pm_mutex held, unless the suspend/hibernate code is * guaranteed not to run in parallel with that modification). */ -void set_gfp_allowed_mask(gfp_t mask) + +static gfp_t saved_gfp_mask; + +void pm_restore_gfp_mask(void) { WARN_ON(!mutex_is_locked(&pm_mutex)); - gfp_allowed_mask = mask; + if (saved_gfp_mask) { + gfp_allowed_mask = saved_gfp_mask; + saved_gfp_mask = 0; + } } -gfp_t clear_gfp_allowed_mask(gfp_t mask) +void pm_restrict_gfp_mask(void) { - gfp_t ret = gfp_allowed_mask; - WARN_ON(!mutex_is_locked(&pm_mutex)); - gfp_allowed_mask &= ~mask; - return ret; + WARN_ON(saved_gfp_mask); + saved_gfp_mask = gfp_allowed_mask; + gfp_allowed_mask &= ~GFP_IOFS; } #endif /* CONFIG_PM_SLEEP */ -- cgit v1.2.3 From e31b71b96e2440fd0f664443d1b1ecdf57b0bf5a Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Sun, 28 Nov 2010 19:46:50 -0200 Subject: wmi: use memcmp instead of strncmp to compare GUIDs commit 8b14d7b22c61f17ccb869e0047d9df6dd9f50a9f upstream. While looking for the duplicates in /sys/class/wmi/, I couldn't find them. The code that looks for duplicates uses strncmp in a binary GUID, which may contain zero bytes. The right function is memcmp, which is also used in another section of wmi code. It was finding 49142400-C6A3-40FA-BADB-8A2652834100 as a duplicate of 39142400-C6A3-40FA-BADB-8A2652834100. Since the first byte is the fourth printed, they were found as equal by strncmp. Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/platform/x86/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index e4eaa14ed987..0ffeb8f11ab5 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -795,7 +795,7 @@ static bool guid_already_parsed(const char *guid_string) wblock = list_entry(p, struct wmi_block, list); gblock = &wblock->gblock; - if (strncmp(gblock->guid, guid_string, 16) == 0) + if (memcmp(gblock->guid, guid_string, 16) == 0) return true; } return false; -- cgit v1.2.3 From 1a91ff5ceb94c086e2d64de9c811f58155728fd1 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 1 Dec 2010 10:08:01 +0100 Subject: nohz/s390: fix arch_needs_cpu() return value on offline cpus commit 398812159e328478ae49b4bd01f0d71efea96c39 upstream. This fixes the same problem as described in the patch "nohz: fix printk_needs_cpu() return value on offline cpus" for the arch_needs_cpu() primitive: arch_needs_cpu() may return 1 if called on offline cpus. When a cpu gets offlined it schedules the idle process which, before killing its own cpu, will call tick_nohz_stop_sched_tick(). That function in turn will call arch_needs_cpu() in order to check if the local tick can be disabled. On offline cpus this function should naturally return 0 since regardless if the tick gets disabled or not the cpu will be dead short after. That is besides the fact that __cpu_disable() should already have made sure that no interrupts on the offlined cpu will be delivered anyway. In this case it prevents tick_nohz_stop_sched_tick() to call select_nohz_load_balancer(). No idea if that really is a problem. However what made me debug this is that on 2.6.32 the function get_nohz_load_balancer() is used within __mod_timer() to select a cpu on which a timer gets enqueued. If arch_needs_cpu() returns 1 then the nohz_load_balancer cpu doesn't get updated when a cpu gets offlined. It may contain the cpu number of an offline cpu. In turn timers get enqueued on an offline cpu and not very surprisingly they never expire and cause system hangs. This has been observed 2.6.32 kernels. On current kernels __mod_timer() uses get_nohz_timer_target() which doesn't have that problem. However there might be other problems because of the too early exit tick_nohz_stop_sched_tick() in case a cpu goes offline. This specific bug was indrocuded with 3c5d92a0 "nohz: Introduce arch_needs_cpu". In this case a cpu hotplug notifier is used to fix the issue in order to keep the normal/fast path small. All we need to do is to clear the condition that makes arch_needs_cpu() return 1 since it is just a performance improvement which is supposed to keep the local tick running for a short period if a cpu goes idle. Nothing special needs to be done except for clearing the condition. Acked-by: Peter Zijlstra Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/s390/kernel/vtime.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 3479f1b0d4e0..c1e326cedea5 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -565,6 +566,23 @@ void init_cpu_vtimer(void) __ctl_set_bit(0,10); } +static int __cpuinit s390_nohz_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + struct s390_idle_data *idle; + long cpu = (long) hcpu; + + idle = &per_cpu(s390_idle, cpu); + switch (action) { + case CPU_DYING: + case CPU_DYING_FROZEN: + idle->nohz_delay = 0; + default: + break; + } + return NOTIFY_OK; +} + void __init vtime_init(void) { /* request the cpu timer external interrupt */ @@ -573,5 +591,6 @@ void __init vtime_init(void) /* Enable cpu timer interrupts on the boot cpu. */ init_cpu_vtimer(); + cpu_notifier(s390_nohz_notify, 0); } -- cgit v1.2.3 From 32005932e9aa0c2b97fd817edde2dff1c5640734 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 30 Nov 2010 17:36:08 +0900 Subject: genirq: Fix incorrect proc spurious output commit 25c9170ed64a6551beefe9315882f754e14486f4 upstream. Since commit a1afb637(switch /proc/irq/*/spurious to seq_file) all /proc/irq/XX/spurious files show the information of irq 0. Current irq_spurious_proc_open() passes on NULL as the 3rd argument, which is used as an IRQ number in irq_spurious_proc_show(), to the single_open(). Because of this, all the /proc/irq/XX/spurious file shows IRQ 0 information regardless of the IRQ number. To fix the problem, irq_spurious_proc_open() must pass on the appropreate data (IRQ number) to single_open(). Signed-off-by: Kenji Kaneshige Signed-off-by: Andi Kleen Reviewed-by: Yong Zhang LKML-Reference: <4CF4B778.90604@jp.fujitsu.com> Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/irq/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index 09a2ee540bd2..345e0b75fe1e 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -214,7 +214,7 @@ static int irq_spurious_proc_show(struct seq_file *m, void *v) static int irq_spurious_proc_open(struct inode *inode, struct file *file) { - return single_open(file, irq_spurious_proc_show, NULL); + return single_open(file, irq_spurious_proc_show, PDE(inode)->data); } static const struct file_operations irq_spurious_proc_fops = { -- cgit v1.2.3 From 8fb9ee234b8283ced0b5d47c26739144a254a1ed Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 30 Oct 2010 16:43:10 -0700 Subject: net: Truncate recvfrom and sendto length to INT_MAX. commit 253eacc070b114c2ec1f81b067d2fed7305467b0 upstream. Signed-off-by: Linus Torvalds Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/socket.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/socket.c b/net/socket.c index 367d5477d00f..166ad32f9448 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1652,6 +1652,8 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, struct iovec iov; int fput_needed; + if (len > INT_MAX) + len = INT_MAX; sock = sockfd_lookup_light(fd, &err, &fput_needed); if (!sock) goto out; @@ -1709,6 +1711,8 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, int err, err2; int fput_needed; + if (size > INT_MAX) + size = INT_MAX; sock = sockfd_lookup_light(fd, &err, &fput_needed); if (!sock) goto out; -- cgit v1.2.3 From 8bb1509c521bde108dcd1bd787e0e5ac9db49157 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Oct 2010 11:41:55 -0700 Subject: net: Limit socket I/O iovec total length to INT_MAX. commit 8acfe468b0384e834a303f08ebc4953d72fb690a upstream. This helps protect us from overflow issues down in the individual protocol sendmsg/recvmsg handlers. Once we hit INT_MAX we truncate out the rest of the iovec by setting the iov_len members to zero. This works because: 1) For SOCK_STREAM and SOCK_SEQPACKET sockets, partial writes are allowed and the application will just continue with another write to send the rest of the data. 2) For datagram oriented sockets, where there must be a one-to-one correspondance between write() calls and packets on the wire, INT_MAX is going to be far larger than the packet size limit the protocol is going to check for and signal with -EMSGSIZE. Based upon a patch by Linus Torvalds. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/compat.c | 10 ++++++---- net/core/iovec.c | 15 +++++++-------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/net/compat.c b/net/compat.c index ec24d9edb025..b8695349e40e 100644 --- a/net/compat.c +++ b/net/compat.c @@ -41,10 +41,12 @@ static inline int iov_from_user_compat_to_kern(struct iovec *kiov, compat_size_t len; if (get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } + get_user(buf, &uiov32->iov_base)) + return -EFAULT; + + if (len > INT_MAX - tot_len) + len = INT_MAX - tot_len; + tot_len += len; kiov->iov_base = compat_ptr(buf); kiov->iov_len = (__kernel_size_t) len; diff --git a/net/core/iovec.c b/net/core/iovec.c index 1e7f4e91a935..4198d73b119b 100644 --- a/net/core/iovec.c +++ b/net/core/iovec.c @@ -59,14 +59,13 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, err = 0; for (ct = 0; ct < m->msg_iovlen; ct++) { - err += iov[ct].iov_len; - /* - * Goal is not to verify user data, but to prevent returning - * negative value, which is interpreted as errno. - * Overflow is still possible, but it is harmless. - */ - if (err < 0) - return -EMSGSIZE; + size_t len = iov[ct].iov_len; + + if (len > INT_MAX - err) { + len = INT_MAX - err; + iov[ct].iov_len = len; + } + err += len; } return err; -- cgit v1.2.3 From 48d21fcef246f334706d5ac81d34c594915259b0 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 4 Nov 2010 09:12:44 -0700 Subject: Input: i8042 - add Sony VAIO VPCZ122GX to nomux list [Note that the mainline will not have this particular fix but rather will blacklist entire VAIO line based off DMI board name. For stable I am being a bit more cautious and blacklist one particular product.] Trying to query/activate active multiplexing mode on this VAIO makes both keyboard and touchpad inoperable. Futher kernels will blacklist entire VAIO line, however here we blacklist just one particular model. Reported-by: Jesse Barnes Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/input/serio/i8042-x86ia64io.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index ed7ad7416b24..8c53926eb20b 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -332,6 +332,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), }, }, + { + /* Sony Vaio VPCZ122GX */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCZ122GX"), + }, + }, { /* Sony Vaio FS-115b */ .matches = { -- cgit v1.2.3 From 6ed9ced224293bad65454671d472eebeb53cb7ba Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 11 Oct 2010 14:18:45 -0700 Subject: omap: dma: Fix buffering disable bit setting for omap24xx commit 3e57f1626b5febe5cc99aa6870377deef3ae03cc upstream. An errata workaround for omap24xx is not setting the buffering disable bit 25 what is the purpose but channel enable bit 7 instead. Background for this fix is the DMA stalling issue with ASoC omap-mcbsp driver. Peter Ujfalusi has found an issue in recording that the DMA stall could happen if there were a buffer overrun detected by ALSA and the DMA was stopped and restarted due that. This problem is known to occur on both OMAP2420 and OMAP3. It can recover on OMAP3 after dma free, dma request and reconfiguration cycle. However, on OMAP2420 it seems that only way to recover is a reset. Problem was not visible before the commit c12abc0. That commit changed that the McBSP transmitter/receiver is released from reset only when needed. That is, only enabled McBSP transmitter without transmission was able to prevent this DMA stall problem in receiving side and underlying problem did not show up until now. McBSP transmitter itself seems to no be reason since DMA stall does not recover by enabling the transmission after stall. Debugging showed that there were a DMA write active during DMA stop time and it never completed even when restarting the DMA. Experimenting showed that the DMA buffering disable bit could be used to avoid stalling when using source synchronized transfers. However that could have performance hit and OMAP3 TRM states that buffering disable is not allowed for destination synchronized transfers so subsequent patch will implement a method to complete DMA writes when stopping. This patch is based on assumtion that complete lock-up on OMAP2420 is different but related problem. I don't have access to OMAP2420 errata but I believe this old workaround here is put for a reason but unfortunately a wrong bit was typed and problem showed up only now. Signed-off-by: Jarkko Nikula Signed-off-by: Peter Ujfalusi Acked-by: Manjunath Kondaiah G Signed-off-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/arm/plat-omap/dma.c | 14 ++++++++++---- arch/arm/plat-omap/include/plat/dma.h | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index f7f571e7987e..4f332f0df217 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -993,11 +993,17 @@ void omap_start_dma(int lch) l = dma_read(CCR(lch)); /* - * Errata: On ES2.0 BUFFERING disable must be set. - * This will always fail on ES1.0 + * Errata: Inter Frame DMA buffering issue (All OMAP2420 and + * OMAP2430ES1.0): DMA will wrongly buffer elements if packing and + * bursting is enabled. This might result in data gets stalled in + * FIFO at the end of the block. + * Workaround: DMA channels must have BUFFERING_DISABLED bit set to + * guarantee no data will stay in the DMA FIFO in case inter frame + * buffering occurs. */ - if (cpu_is_omap24xx()) - l |= OMAP_DMA_CCR_EN; + if (cpu_is_omap2420() || + (cpu_is_omap2430() && (omap_type() == OMAP2430_REV_ES1_0))) + l |= OMAP_DMA_CCR_BUFFERING_DISABLE; l |= OMAP_DMA_CCR_EN; dma_write(l, CCR(lch)); diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index 02232ca2c37f..118c486efd75 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h @@ -335,6 +335,7 @@ #define OMAP2_DMA_MISALIGNED_ERR_IRQ (1 << 11) #define OMAP_DMA_CCR_EN (1 << 7) +#define OMAP_DMA_CCR_BUFFERING_DISABLE (1 << 25) #define OMAP_DMA_DATA_TYPE_S8 0x00 #define OMAP_DMA_DATA_TYPE_S16 0x01 -- cgit v1.2.3 From a4e606c0633166f26e1456ed9bd86a185216cccb Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 11 Oct 2010 14:18:56 -0700 Subject: OMAP3: DMA: Errata i541: sDMA FIFO draining does not finish commit 0e4905c0199d683497833be60a428c784d7575b8 upstream. Implement the suggested workaround for OMAP3 regarding to sDMA draining issue, when the channel is disabled on the fly. This errata affects the following configuration: sDMA transfer is source synchronized Buffering is enabled SmartStandby is selected. The issue can be easily reproduced by creating overrun situation while recording audio. Either introduce load to the CPU: nice -19 arecord -D hw:0 -M -B 10000 -F 5000 -f dat > /dev/null & \ dd if=/dev/urandom of=/dev/null or suspending the arecord, and resuming it: arecord -D hw:0 -M -B 10000 -F 5000 -f dat > /dev/null CTRL+Z; fg; CTRL+Z; fg; ... In case of overrun audio stops DMA, and restarts it (without reseting the sDMA channel). When we hit this errata in stop case (sDMA drain did not complete), at the coming start the sDMA will not going to be operational (it is still draining). This leads to DMA stall condition. On OMAP3 we can recover with sDMA channel reset, it has been observed that by introducing unrelated sDMA activity might also help (reading from MMC for example). The same errata exists for OMAP2, where the suggestion is to disable the buffering to avoid this type of error. On OMAP3 the suggestion is to set sDMA to NoStandby before disabling the channel, and wait for the drain to finish, than configure sDMA to SmartStandby again. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Andi Kleen Acked-by : Santosh Shilimkar Acked-by : Manjunath Kondaiah G Signed-off-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman --- arch/arm/plat-omap/dma.c | 36 +++++++++++++++++++++++++++++++++-- arch/arm/plat-omap/include/plat/dma.h | 3 +++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 4f332f0df217..087e81a092a6 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -1021,8 +1022,39 @@ void omap_stop_dma(int lch) dma_write(0, CICR(lch)); l = dma_read(CCR(lch)); - l &= ~OMAP_DMA_CCR_EN; - dma_write(l, CCR(lch)); + /* OMAP3 Errata i541: sDMA FIFO draining does not finish */ + if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) { + int i = 0; + u32 sys_cf; + + /* Configure No-Standby */ + l = dma_read(OCP_SYSCONFIG); + sys_cf = l; + l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK; + l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE); + dma_write(l , OCP_SYSCONFIG); + + l = dma_read(CCR(lch)); + l &= ~OMAP_DMA_CCR_EN; + dma_write(l, CCR(lch)); + + /* Wait for sDMA FIFO drain */ + l = dma_read(CCR(lch)); + while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE | + OMAP_DMA_CCR_WR_ACTIVE))) { + udelay(5); + i++; + l = dma_read(CCR(lch)); + } + if (i >= 100) + printk(KERN_ERR "DMA drain did not complete on " + "lch %d\n", lch); + /* Restore OCP_SYSCONFIG */ + dma_write(sys_cf, OCP_SYSCONFIG); + } else { + l &= ~OMAP_DMA_CCR_EN; + dma_write(l, CCR(lch)); + } if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { int next_lch, cur_lch = lch; diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index 118c486efd75..6b78986d8d5b 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h @@ -335,6 +335,9 @@ #define OMAP2_DMA_MISALIGNED_ERR_IRQ (1 << 11) #define OMAP_DMA_CCR_EN (1 << 7) +#define OMAP_DMA_CCR_RD_ACTIVE (1 << 9) +#define OMAP_DMA_CCR_WR_ACTIVE (1 << 10) +#define OMAP_DMA_CCR_SEL_SRC_DST_SYNC (1 << 24) #define OMAP_DMA_CCR_BUFFERING_DISABLE (1 << 25) #define OMAP_DMA_DATA_TYPE_S8 0x00 -- cgit v1.2.3 From 5cd63b34258b056b568b05582310e966aa65d2fd Mon Sep 17 00:00:00 2001 From: andrew hendry Date: Wed, 3 Nov 2010 12:54:53 +0000 Subject: memory corruption in X.25 facilities parsing commit a6331d6f9a4298173b413cf99a40cc86a9d92c37 upstream. Signed-of-by: Andrew Hendry Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/x25/x25_facilities.c | 8 ++++---- net/x25/x25_in.c | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index 771bab00754b..3a8c4c419cd4 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c @@ -134,15 +134,15 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, case X25_FAC_CLASS_D: switch (*p) { case X25_FAC_CALLING_AE: - if (p[1] > X25_MAX_DTE_FACIL_LEN) - break; + if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1) + return 0; dte_facs->calling_len = p[2]; memcpy(dte_facs->calling_ae, &p[3], p[1] - 1); *vc_fac_mask |= X25_MASK_CALLING_AE; break; case X25_FAC_CALLED_AE: - if (p[1] > X25_MAX_DTE_FACIL_LEN) - break; + if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1) + return 0; dte_facs->called_len = p[2]; memcpy(dte_facs->called_ae, &p[3], p[1] - 1); *vc_fac_mask |= X25_MASK_CALLED_AE; diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index 63178961efac..f729f022be69 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c @@ -119,6 +119,8 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp &x25->vc_facil_mask); if (len > 0) skb_pull(skb, len); + else + return -1; /* * Copy any Call User Data. */ -- cgit v1.2.3 From 69caa40820b6f142cae5485bd61362bb1dfcc12c Mon Sep 17 00:00:00 2001 From: Hagen Paul Pfeifer Date: Sat, 19 Jun 2010 17:05:36 +0000 Subject: net: optimize Berkeley Packet Filter (BPF) processing Gcc is currenlty not in the ability to optimize the switch statement in sk_run_filter() because of dense case labels. This patch replace the OR'd labels with ordered sequenced case labels. The sk_chk_filter() function is modified to patch/replace the original OPCODES in a ordered but equivalent form. gcc is now in the ability to transform the switch statement in sk_run_filter into a jump table of complexity O(1). Until this patch gcc generates a sequence of conditional branches (O(n) of 567 byte .text segment size (arch x86_64): 7ff: 8b 06 mov (%rsi),%eax 801: 66 83 f8 35 cmp $0x35,%ax 805: 0f 84 d0 02 00 00 je adb 80b: 0f 87 07 01 00 00 ja 918 811: 66 83 f8 15 cmp $0x15,%ax 815: 0f 84 c5 02 00 00 je ae0 81b: 77 73 ja 890 81d: 66 83 f8 04 cmp $0x4,%ax 821: 0f 84 17 02 00 00 je a3e 827: 77 29 ja 852 829: 66 83 f8 01 cmp $0x1,%ax [...] With the modification the compiler translate the switch statement into the following jump table fragment: 7ff: 66 83 3e 2c cmpw $0x2c,(%rsi) 803: 0f 87 1f 02 00 00 ja a28 809: 0f b7 06 movzwl (%rsi),%eax 80c: ff 24 c5 00 00 00 00 jmpq *0x0(,%rax,8) 813: 44 89 e3 mov %r12d,%ebx 816: e9 43 03 00 00 jmpq b5e 81b: 41 89 dc mov %ebx,%r12d 81e: e9 3b 03 00 00 jmpq b5e Furthermore, I reordered the instructions to reduce cache line misses by order the most common instruction to the start. [AK: Added as dependency on next patch] Signed-off-by: Hagen Paul Pfeifer Signed-off-by: David S. Miller Signed-off-by: Andi Kleen --- include/linux/filter.h | 48 +++++++++++ net/core/filter.c | 212 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 209 insertions(+), 51 deletions(-) diff --git a/include/linux/filter.h b/include/linux/filter.h index 151f5d703b7e..69b43dbea6c6 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -91,6 +91,54 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */ #define BPF_TAX 0x00 #define BPF_TXA 0x80 +enum { + BPF_S_RET_K = 0, + BPF_S_RET_A, + BPF_S_ALU_ADD_K, + BPF_S_ALU_ADD_X, + BPF_S_ALU_SUB_K, + BPF_S_ALU_SUB_X, + BPF_S_ALU_MUL_K, + BPF_S_ALU_MUL_X, + BPF_S_ALU_DIV_X, + BPF_S_ALU_AND_K, + BPF_S_ALU_AND_X, + BPF_S_ALU_OR_K, + BPF_S_ALU_OR_X, + BPF_S_ALU_LSH_K, + BPF_S_ALU_LSH_X, + BPF_S_ALU_RSH_K, + BPF_S_ALU_RSH_X, + BPF_S_ALU_NEG, + BPF_S_LD_W_ABS, + BPF_S_LD_H_ABS, + BPF_S_LD_B_ABS, + BPF_S_LD_W_LEN, + BPF_S_LD_W_IND, + BPF_S_LD_H_IND, + BPF_S_LD_B_IND, + BPF_S_LD_IMM, + BPF_S_LDX_W_LEN, + BPF_S_LDX_B_MSH, + BPF_S_LDX_IMM, + BPF_S_MISC_TAX, + BPF_S_MISC_TXA, + BPF_S_ALU_DIV_K, + BPF_S_LD_MEM, + BPF_S_LDX_MEM, + BPF_S_ST, + BPF_S_STX, + BPF_S_JMP_JA, + BPF_S_JMP_JEQ_K, + BPF_S_JMP_JEQ_X, + BPF_S_JMP_JGE_K, + BPF_S_JMP_JGE_X, + BPF_S_JMP_JGT_K, + BPF_S_JMP_JGT_X, + BPF_S_JMP_JSET_K, + BPF_S_JMP_JSET_X, +}; + #ifndef BPF_MAXINSNS #define BPF_MAXINSNS 4096 #endif diff --git a/net/core/filter.c b/net/core/filter.c index da69fb728d32..52b051f82a01 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -128,87 +128,87 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int fentry = &filter[pc]; switch (fentry->code) { - case BPF_ALU|BPF_ADD|BPF_X: + case BPF_S_ALU_ADD_X: A += X; continue; - case BPF_ALU|BPF_ADD|BPF_K: + case BPF_S_ALU_ADD_K: A += fentry->k; continue; - case BPF_ALU|BPF_SUB|BPF_X: + case BPF_S_ALU_SUB_X: A -= X; continue; - case BPF_ALU|BPF_SUB|BPF_K: + case BPF_S_ALU_SUB_K: A -= fentry->k; continue; - case BPF_ALU|BPF_MUL|BPF_X: + case BPF_S_ALU_MUL_X: A *= X; continue; - case BPF_ALU|BPF_MUL|BPF_K: + case BPF_S_ALU_MUL_K: A *= fentry->k; continue; - case BPF_ALU|BPF_DIV|BPF_X: + case BPF_S_ALU_DIV_X: if (X == 0) return 0; A /= X; continue; - case BPF_ALU|BPF_DIV|BPF_K: + case BPF_S_ALU_DIV_K: A /= fentry->k; continue; - case BPF_ALU|BPF_AND|BPF_X: + case BPF_S_ALU_AND_X: A &= X; continue; - case BPF_ALU|BPF_AND|BPF_K: + case BPF_S_ALU_AND_K: A &= fentry->k; continue; - case BPF_ALU|BPF_OR|BPF_X: + case BPF_S_ALU_OR_X: A |= X; continue; - case BPF_ALU|BPF_OR|BPF_K: + case BPF_S_ALU_OR_K: A |= fentry->k; continue; - case BPF_ALU|BPF_LSH|BPF_X: + case BPF_S_ALU_LSH_X: A <<= X; continue; - case BPF_ALU|BPF_LSH|BPF_K: + case BPF_S_ALU_LSH_K: A <<= fentry->k; continue; - case BPF_ALU|BPF_RSH|BPF_X: + case BPF_S_ALU_RSH_X: A >>= X; continue; - case BPF_ALU|BPF_RSH|BPF_K: + case BPF_S_ALU_RSH_K: A >>= fentry->k; continue; - case BPF_ALU|BPF_NEG: + case BPF_S_ALU_NEG: A = -A; continue; - case BPF_JMP|BPF_JA: + case BPF_S_JMP_JA: pc += fentry->k; continue; - case BPF_JMP|BPF_JGT|BPF_K: + case BPF_S_JMP_JGT_K: pc += (A > fentry->k) ? fentry->jt : fentry->jf; continue; - case BPF_JMP|BPF_JGE|BPF_K: + case BPF_S_JMP_JGE_K: pc += (A >= fentry->k) ? fentry->jt : fentry->jf; continue; - case BPF_JMP|BPF_JEQ|BPF_K: + case BPF_S_JMP_JEQ_K: pc += (A == fentry->k) ? fentry->jt : fentry->jf; continue; - case BPF_JMP|BPF_JSET|BPF_K: + case BPF_S_JMP_JSET_K: pc += (A & fentry->k) ? fentry->jt : fentry->jf; continue; - case BPF_JMP|BPF_JGT|BPF_X: + case BPF_S_JMP_JGT_X: pc += (A > X) ? fentry->jt : fentry->jf; continue; - case BPF_JMP|BPF_JGE|BPF_X: + case BPF_S_JMP_JGE_X: pc += (A >= X) ? fentry->jt : fentry->jf; continue; - case BPF_JMP|BPF_JEQ|BPF_X: + case BPF_S_JMP_JEQ_X: pc += (A == X) ? fentry->jt : fentry->jf; continue; - case BPF_JMP|BPF_JSET|BPF_X: + case BPF_S_JMP_JSET_X: pc += (A & X) ? fentry->jt : fentry->jf; continue; - case BPF_LD|BPF_W|BPF_ABS: + case BPF_S_LD_W_ABS: k = fentry->k; load_w: ptr = load_pointer(skb, k, 4, &tmp); @@ -217,7 +217,7 @@ load_w: continue; } break; - case BPF_LD|BPF_H|BPF_ABS: + case BPF_S_LD_H_ABS: k = fentry->k; load_h: ptr = load_pointer(skb, k, 2, &tmp); @@ -226,7 +226,7 @@ load_h: continue; } break; - case BPF_LD|BPF_B|BPF_ABS: + case BPF_S_LD_B_ABS: k = fentry->k; load_b: ptr = load_pointer(skb, k, 1, &tmp); @@ -235,54 +235,54 @@ load_b: continue; } break; - case BPF_LD|BPF_W|BPF_LEN: + case BPF_S_LD_W_LEN: A = skb->len; continue; - case BPF_LDX|BPF_W|BPF_LEN: + case BPF_S_LDX_W_LEN: X = skb->len; continue; - case BPF_LD|BPF_W|BPF_IND: + case BPF_S_LD_W_IND: k = X + fentry->k; goto load_w; - case BPF_LD|BPF_H|BPF_IND: + case BPF_S_LD_H_IND: k = X + fentry->k; goto load_h; - case BPF_LD|BPF_B|BPF_IND: + case BPF_S_LD_B_IND: k = X + fentry->k; goto load_b; - case BPF_LDX|BPF_B|BPF_MSH: + case BPF_S_LDX_B_MSH: ptr = load_pointer(skb, fentry->k, 1, &tmp); if (ptr != NULL) { X = (*(u8 *)ptr & 0xf) << 2; continue; } return 0; - case BPF_LD|BPF_IMM: + case BPF_S_LD_IMM: A = fentry->k; continue; - case BPF_LDX|BPF_IMM: + case BPF_S_LDX_IMM: X = fentry->k; continue; - case BPF_LD|BPF_MEM: + case BPF_S_LD_MEM: A = mem[fentry->k]; continue; - case BPF_LDX|BPF_MEM: + case BPF_S_LDX_MEM: X = mem[fentry->k]; continue; - case BPF_MISC|BPF_TAX: + case BPF_S_MISC_TAX: X = A; continue; - case BPF_MISC|BPF_TXA: + case BPF_S_MISC_TXA: A = X; continue; - case BPF_RET|BPF_K: + case BPF_S_RET_K: return fentry->k; - case BPF_RET|BPF_A: + case BPF_S_RET_A: return A; - case BPF_ST: + case BPF_S_ST: mem[fentry->k] = A; continue; - case BPF_STX: + case BPF_S_STX: mem[fentry->k] = X; continue; default: @@ -390,53 +390,128 @@ int sk_chk_filter(struct sock_filter *filter, int flen) /* Only allow valid instructions */ switch (ftest->code) { case BPF_ALU|BPF_ADD|BPF_K: + ftest->code = BPF_S_ALU_ADD_K; + break; case BPF_ALU|BPF_ADD|BPF_X: + ftest->code = BPF_S_ALU_ADD_X; + break; case BPF_ALU|BPF_SUB|BPF_K: + ftest->code = BPF_S_ALU_SUB_K; + break; case BPF_ALU|BPF_SUB|BPF_X: + ftest->code = BPF_S_ALU_SUB_X; + break; case BPF_ALU|BPF_MUL|BPF_K: + ftest->code = BPF_S_ALU_MUL_K; + break; case BPF_ALU|BPF_MUL|BPF_X: + ftest->code = BPF_S_ALU_MUL_X; + break; case BPF_ALU|BPF_DIV|BPF_X: + ftest->code = BPF_S_ALU_DIV_X; + break; case BPF_ALU|BPF_AND|BPF_K: + ftest->code = BPF_S_ALU_AND_K; + break; case BPF_ALU|BPF_AND|BPF_X: + ftest->code = BPF_S_ALU_AND_X; + break; case BPF_ALU|BPF_OR|BPF_K: + ftest->code = BPF_S_ALU_OR_K; + break; case BPF_ALU|BPF_OR|BPF_X: + ftest->code = BPF_S_ALU_OR_X; + break; case BPF_ALU|BPF_LSH|BPF_K: + ftest->code = BPF_S_ALU_LSH_K; + break; case BPF_ALU|BPF_LSH|BPF_X: + ftest->code = BPF_S_ALU_LSH_X; + break; case BPF_ALU|BPF_RSH|BPF_K: + ftest->code = BPF_S_ALU_RSH_K; + break; case BPF_ALU|BPF_RSH|BPF_X: + ftest->code = BPF_S_ALU_RSH_X; + break; case BPF_ALU|BPF_NEG: + ftest->code = BPF_S_ALU_NEG; + break; case BPF_LD|BPF_W|BPF_ABS: + ftest->code = BPF_S_LD_W_ABS; + break; case BPF_LD|BPF_H|BPF_ABS: + ftest->code = BPF_S_LD_H_ABS; + break; case BPF_LD|BPF_B|BPF_ABS: + ftest->code = BPF_S_LD_B_ABS; + break; case BPF_LD|BPF_W|BPF_LEN: + ftest->code = BPF_S_LD_W_LEN; + break; case BPF_LD|BPF_W|BPF_IND: + ftest->code = BPF_S_LD_W_IND; + break; case BPF_LD|BPF_H|BPF_IND: + ftest->code = BPF_S_LD_H_IND; + break; case BPF_LD|BPF_B|BPF_IND: + ftest->code = BPF_S_LD_B_IND; + break; case BPF_LD|BPF_IMM: + ftest->code = BPF_S_LD_IMM; + break; case BPF_LDX|BPF_W|BPF_LEN: + ftest->code = BPF_S_LDX_W_LEN; + break; case BPF_LDX|BPF_B|BPF_MSH: + ftest->code = BPF_S_LDX_B_MSH; + break; case BPF_LDX|BPF_IMM: + ftest->code = BPF_S_LDX_IMM; + break; case BPF_MISC|BPF_TAX: + ftest->code = BPF_S_MISC_TAX; + break; case BPF_MISC|BPF_TXA: + ftest->code = BPF_S_MISC_TXA; + break; case BPF_RET|BPF_K: + ftest->code = BPF_S_RET_K; + break; case BPF_RET|BPF_A: + ftest->code = BPF_S_RET_A; break; /* Some instructions need special checks */ - case BPF_ALU|BPF_DIV|BPF_K: /* check for division by zero */ + case BPF_ALU|BPF_DIV|BPF_K: if (ftest->k == 0) return -EINVAL; + ftest->code = BPF_S_ALU_DIV_K; break; + /* check for invalid memory addresses */ case BPF_LD|BPF_MEM: + if (ftest->k >= BPF_MEMWORDS) + return -EINVAL; + ftest->code = BPF_S_LD_MEM; + break; case BPF_LDX|BPF_MEM: + if (ftest->k >= BPF_MEMWORDS) + return -EINVAL; + ftest->code = BPF_S_LDX_MEM; + break; case BPF_ST: + if (ftest->k >= BPF_MEMWORDS) + return -EINVAL; + ftest->code = BPF_S_ST; + break; case BPF_STX: - /* check for invalid memory addresses */ if (ftest->k >= BPF_MEMWORDS) return -EINVAL; + ftest->code = BPF_S_STX; break; case BPF_JMP|BPF_JA: @@ -447,28 +522,63 @@ int sk_chk_filter(struct sock_filter *filter, int flen) */ if (ftest->k >= (unsigned)(flen-pc-1)) return -EINVAL; + ftest->code = BPF_S_JMP_JA; break; case BPF_JMP|BPF_JEQ|BPF_K: + ftest->code = BPF_S_JMP_JEQ_K; + break; case BPF_JMP|BPF_JEQ|BPF_X: + ftest->code = BPF_S_JMP_JEQ_X; + break; case BPF_JMP|BPF_JGE|BPF_K: + ftest->code = BPF_S_JMP_JGE_K; + break; case BPF_JMP|BPF_JGE|BPF_X: + ftest->code = BPF_S_JMP_JGE_X; + break; case BPF_JMP|BPF_JGT|BPF_K: + ftest->code = BPF_S_JMP_JGT_K; + break; case BPF_JMP|BPF_JGT|BPF_X: + ftest->code = BPF_S_JMP_JGT_X; + break; case BPF_JMP|BPF_JSET|BPF_K: + ftest->code = BPF_S_JMP_JSET_K; + break; case BPF_JMP|BPF_JSET|BPF_X: + ftest->code = BPF_S_JMP_JSET_X; + break; + + default: + return -EINVAL; + } + /* for conditionals both must be safe */ + switch (ftest->code) { + case BPF_S_JMP_JEQ_K: + case BPF_S_JMP_JEQ_X: + case BPF_S_JMP_JGE_K: + case BPF_S_JMP_JGE_X: + case BPF_S_JMP_JGT_K: + case BPF_S_JMP_JGT_X: + case BPF_S_JMP_JSET_X: + case BPF_S_JMP_JSET_K: if (pc + ftest->jt + 1 >= flen || pc + ftest->jf + 1 >= flen) return -EINVAL; - break; + } + } + /* last instruction must be a RET code */ + switch (filter[flen - 1].code) { + case BPF_S_RET_K: + case BPF_S_RET_A: + return 0; + break; default: return -EINVAL; } - } - - return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL; } EXPORT_SYMBOL(sk_chk_filter); -- cgit v1.2.3 From 7bac9815cc7489f880db12ada19b3f10d1db1629 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Nov 2010 10:38:24 -0800 Subject: filter: make sure filters dont read uninitialized memory commit 57fe93b374a6b8711995c2d466c502af9f3a08bb upstream. There is a possibility malicious users can get limited information about uninitialized stack mem array. Even if sk_run_filter() result is bound to packet length (0 .. 65535), we could imagine this can be used by hostile user. Initializing mem[] array, like Dan Rosenberg suggested in his patch is expensive since most filters dont even use this array. Its hard to make the filter validation in sk_chk_filter(), because of the jumps. This might be done later. In this patch, I use a bitmap (a single long var) so that only filters using mem[] loads/stores pay the price of added security checks. For other filters, additional cost is a single instruction. [ Since we access fentry->k a lot now, cache it in a local variable and mark filter entry pointer as const. -DaveM ] Reported-by: Dan Rosenberg Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/core/filter.c | 64 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/net/core/filter.c b/net/core/filter.c index 52b051f82a01..f68e49774829 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -112,39 +112,41 @@ EXPORT_SYMBOL(sk_filter); */ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen) { - struct sock_filter *fentry; /* We walk down these */ void *ptr; u32 A = 0; /* Accumulator */ u32 X = 0; /* Index Register */ u32 mem[BPF_MEMWORDS]; /* Scratch Memory Store */ + unsigned long memvalid = 0; u32 tmp; int k; int pc; + BUILD_BUG_ON(BPF_MEMWORDS > BITS_PER_LONG); /* * Process array of filter instructions. */ for (pc = 0; pc < flen; pc++) { - fentry = &filter[pc]; + const struct sock_filter *fentry = &filter[pc]; + u32 f_k = fentry->k; switch (fentry->code) { case BPF_S_ALU_ADD_X: A += X; continue; case BPF_S_ALU_ADD_K: - A += fentry->k; + A += f_k; continue; case BPF_S_ALU_SUB_X: A -= X; continue; case BPF_S_ALU_SUB_K: - A -= fentry->k; + A -= f_k; continue; case BPF_S_ALU_MUL_X: A *= X; continue; case BPF_S_ALU_MUL_K: - A *= fentry->k; + A *= f_k; continue; case BPF_S_ALU_DIV_X: if (X == 0) @@ -152,49 +154,49 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int A /= X; continue; case BPF_S_ALU_DIV_K: - A /= fentry->k; + A /= f_k; continue; case BPF_S_ALU_AND_X: A &= X; continue; case BPF_S_ALU_AND_K: - A &= fentry->k; + A &= f_k; continue; case BPF_S_ALU_OR_X: A |= X; continue; case BPF_S_ALU_OR_K: - A |= fentry->k; + A |= f_k; continue; case BPF_S_ALU_LSH_X: A <<= X; continue; case BPF_S_ALU_LSH_K: - A <<= fentry->k; + A <<= f_k; continue; case BPF_S_ALU_RSH_X: A >>= X; continue; case BPF_S_ALU_RSH_K: - A >>= fentry->k; + A >>= f_k; continue; case BPF_S_ALU_NEG: A = -A; continue; case BPF_S_JMP_JA: - pc += fentry->k; + pc += f_k; continue; case BPF_S_JMP_JGT_K: - pc += (A > fentry->k) ? fentry->jt : fentry->jf; + pc += (A > f_k) ? fentry->jt : fentry->jf; continue; case BPF_S_JMP_JGE_K: - pc += (A >= fentry->k) ? fentry->jt : fentry->jf; + pc += (A >= f_k) ? fentry->jt : fentry->jf; continue; case BPF_S_JMP_JEQ_K: - pc += (A == fentry->k) ? fentry->jt : fentry->jf; + pc += (A == f_k) ? fentry->jt : fentry->jf; continue; case BPF_S_JMP_JSET_K: - pc += (A & fentry->k) ? fentry->jt : fentry->jf; + pc += (A & f_k) ? fentry->jt : fentry->jf; continue; case BPF_S_JMP_JGT_X: pc += (A > X) ? fentry->jt : fentry->jf; @@ -209,7 +211,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int pc += (A & X) ? fentry->jt : fentry->jf; continue; case BPF_S_LD_W_ABS: - k = fentry->k; + k = f_k; load_w: ptr = load_pointer(skb, k, 4, &tmp); if (ptr != NULL) { @@ -218,7 +220,7 @@ load_w: } break; case BPF_S_LD_H_ABS: - k = fentry->k; + k = f_k; load_h: ptr = load_pointer(skb, k, 2, &tmp); if (ptr != NULL) { @@ -227,7 +229,7 @@ load_h: } break; case BPF_S_LD_B_ABS: - k = fentry->k; + k = f_k; load_b: ptr = load_pointer(skb, k, 1, &tmp); if (ptr != NULL) { @@ -242,32 +244,34 @@ load_b: X = skb->len; continue; case BPF_S_LD_W_IND: - k = X + fentry->k; + k = X + f_k; goto load_w; case BPF_S_LD_H_IND: - k = X + fentry->k; + k = X + f_k; goto load_h; case BPF_S_LD_B_IND: - k = X + fentry->k; + k = X + f_k; goto load_b; case BPF_S_LDX_B_MSH: - ptr = load_pointer(skb, fentry->k, 1, &tmp); + ptr = load_pointer(skb, f_k, 1, &tmp); if (ptr != NULL) { X = (*(u8 *)ptr & 0xf) << 2; continue; } return 0; case BPF_S_LD_IMM: - A = fentry->k; + A = f_k; continue; case BPF_S_LDX_IMM: - X = fentry->k; + X = f_k; continue; case BPF_S_LD_MEM: - A = mem[fentry->k]; + A = (memvalid & (1UL << f_k)) ? + mem[f_k] : 0; continue; case BPF_S_LDX_MEM: - X = mem[fentry->k]; + X = (memvalid & (1UL << f_k)) ? + mem[f_k] : 0; continue; case BPF_S_MISC_TAX: X = A; @@ -276,14 +280,16 @@ load_b: A = X; continue; case BPF_S_RET_K: - return fentry->k; + return f_k; case BPF_S_RET_A: return A; case BPF_S_ST: - mem[fentry->k] = A; + memvalid |= 1UL << f_k; + mem[f_k] = A; continue; case BPF_S_STX: - mem[fentry->k] = X; + memvalid |= 1UL << f_k; + mem[f_k] = X; continue; default: WARN_ON(1); -- cgit v1.2.3 From c4b9d85475fe417aa1d4325e350b6bff78a70c17 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Wed, 10 Nov 2010 12:10:30 +0000 Subject: can-bcm: fix minor heap overflow commit 0597d1b99fcfc2c0eada09a698f85ed413d4ba84 upstream. On 64-bit platforms the ASCII representation of a pointer may be up to 17 bytes long. This patch increases the length of the buffer accordingly. http://marc.info/?l=linux-netdev&m=128872251418192&w=2 Reported-by: Dan Rosenberg Signed-off-by: Oliver Hartkopp Signed-off-by: Andi Kleen CC: Linus Torvalds Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/can/bcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/can/bcm.c b/net/can/bcm.c index 08ffe9e4be20..6faa8256e10c 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -125,7 +125,7 @@ struct bcm_sock { struct list_head tx_ops; unsigned long dropped_usr_msgs; struct proc_dir_entry *bcm_proc_read; - char procname [9]; /* pointer printed in ASCII with \0 */ + char procname [20]; /* pointer printed in ASCII with \0 */ }; static inline struct bcm_sock *bcm_sk(const struct sock *sk) -- cgit v1.2.3 From 47a671800b5c4bca9c5826fc18d9a2ac090a5e3c Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Fri, 12 Nov 2010 12:44:42 -0800 Subject: x25: Prevent crashing when parsing bad X.25 facilities commit 5ef41308f94dcbb3b7afc56cdef1c2ba53fa5d2f upstream. Now with improved comma support. On parsing malformed X.25 facilities, decrementing the remaining length may cause it to underflow. Since the length is an unsigned integer, this will result in the loop continuing until the kernel crashes. This patch adds checks to ensure decrementing the remaining length does not cause it to wrap around. Signed-off-by: Dan Rosenberg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/x25/x25_facilities.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index 3a8c4c419cd4..55187c8f6420 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c @@ -61,6 +61,8 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, while (len > 0) { switch (*p & X25_FAC_CLASS_MASK) { case X25_FAC_CLASS_A: + if (len < 2) + return 0; switch (*p) { case X25_FAC_REVERSE: if((p[1] & 0x81) == 0x81) { @@ -104,6 +106,8 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, len -= 2; break; case X25_FAC_CLASS_B: + if (len < 3) + return 0; switch (*p) { case X25_FAC_PACKET_SIZE: facilities->pacsize_in = p[1]; @@ -125,6 +129,8 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, len -= 3; break; case X25_FAC_CLASS_C: + if (len < 4) + return 0; printk(KERN_DEBUG "X.25: unknown facility %02X, " "values %02X, %02X, %02X\n", p[0], p[1], p[2], p[3]); @@ -132,6 +138,8 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, len -= 4; break; case X25_FAC_CLASS_D: + if (len < p[1] + 2) + return 0; switch (*p) { case X25_FAC_CALLING_AE: if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1) @@ -149,9 +157,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, break; default: printk(KERN_DEBUG "X.25: unknown facility %02X," - "length %d, values %02X, %02X, " - "%02X, %02X\n", - p[0], p[1], p[2], p[3], p[4], p[5]); + "length %d\n", p[0], p[1]); break; } len -= p[1] + 2; -- cgit v1.2.3 From 474a751770cdae97c5baa16c4dc2f0e94d0a464f Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 4 Nov 2010 14:38:39 -0400 Subject: crypto: padlock - Fix AES-CBC handling on odd-block-sized input commit c054a076a1bd4731820a9c4d638b13d5c9bf5935 upstream. On certain VIA chipsets AES-CBC requires the input/output to be a multiple of 64 bytes. We had a workaround for this but it was buggy as it sent the whole input for processing when it is meant to only send the initial number of blocks which makes the rest a multiple of 64 bytes. As expected this causes memory corruption whenever the workaround kicks in. Reported-by: Phil Sutter Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/crypto/padlock-aes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 2e992bc8015b..8a515baa38f7 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c @@ -286,7 +286,7 @@ static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key, if (initial) asm volatile (".byte 0xf3,0x0f,0xa7,0xd0" /* rep xcryptcbc */ : "+S" (input), "+D" (output), "+a" (iv) - : "d" (control_word), "b" (key), "c" (count)); + : "d" (control_word), "b" (key), "c" (initial)); asm volatile (".byte 0xf3,0x0f,0xa7,0xd0" /* rep xcryptcbc */ : "+S" (input), "+D" (output), "+a" (iv) -- cgit v1.2.3 From 973a11aa7810c40a80ad064211fa157dd1921b37 Mon Sep 17 00:00:00 2001 From: Phil Blundell Date: Wed, 24 Nov 2010 11:49:19 -0800 Subject: econet: disallow NULL remote addr for sendmsg(), fixes CVE-2010-3849 commit fa0e846494792e722d817b9d3d625a4ef4896c96 upstream. Later parts of econet_sendmsg() rely on saddr != NULL, so return early with EINVAL if NULL was passed otherwise an oops may occur. Signed-off-by: Phil Blundell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/econet/af_econet.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 2a5a8053e000..8170acbe280d 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -297,23 +297,14 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, mutex_lock(&econet_mutex); - if (saddr == NULL) { - struct econet_sock *eo = ec_sk(sk); - - addr.station = eo->station; - addr.net = eo->net; - port = eo->port; - cb = eo->cb; - } else { - if (msg->msg_namelen < sizeof(struct sockaddr_ec)) { - mutex_unlock(&econet_mutex); - return -EINVAL; - } - addr.station = saddr->addr.station; - addr.net = saddr->addr.net; - port = saddr->port; - cb = saddr->cb; - } + if (saddr == NULL || msg->msg_namelen < sizeof(struct sockaddr_ec)) { + mutex_unlock(&econet_mutex); + return -EINVAL; + } + addr.station = saddr->addr.station; + addr.net = saddr->addr.net; + port = saddr->port; + cb = saddr->cb; /* Look for a device with the right network number. */ dev = net2dev_map[addr.net]; @@ -351,7 +342,6 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, eb = (struct ec_cb *)&skb->cb; - /* BUG: saddr may be NULL */ eb->cookie = saddr->cookie; eb->sec = *saddr; eb->sent = ec_tx_done; -- cgit v1.2.3 From 5a7ce7c10112832aa73745faaca297844656138b Mon Sep 17 00:00:00 2001 From: Phil Blundell Date: Wed, 24 Nov 2010 11:49:53 -0800 Subject: econet: fix CVE-2010-3850 commit 16c41745c7b92a243d0874f534c1655196c64b74 upstream. Add missing check for capable(CAP_NET_ADMIN) in SIOCSIFADDR operation. Signed-off-by: Phil Blundell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/econet/af_econet.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 8170acbe280d..cd62e27035ef 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -661,6 +661,9 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg) err = 0; switch (cmd) { case SIOCSIFADDR: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + edev = dev->ec_ptr; if (edev == NULL) { /* Magic up a new one. */ -- cgit v1.2.3 From 8bad5a9770496e333505c129225074f61898c514 Mon Sep 17 00:00:00 2001 From: Phil Blundell Date: Wed, 24 Nov 2010 11:51:47 -0800 Subject: econet: fix CVE-2010-3848 commit a27e13d370415add3487949c60810e36069a23a6 upstream. Don't declare variable sized array of iovecs on the stack since this could cause stack overflow if msg->msgiovlen is large. Instead, coalesce the user-supplied data into a new buffer and use a single iovec for it. Signed-off-by: Phil Blundell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/econet/af_econet.c | 62 +++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index cd62e27035ef..2e41c761f414 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -276,12 +277,12 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, #endif #ifdef CONFIG_ECONET_AUNUDP struct msghdr udpmsg; - struct iovec iov[msg->msg_iovlen+1]; + struct iovec iov[2]; struct aunhdr ah; struct sockaddr_in udpdest; __kernel_size_t size; - int i; mm_segment_t oldfs; + char *userbuf; #endif /* @@ -319,17 +320,17 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, } } - if (len + 15 > dev->mtu) { - mutex_unlock(&econet_mutex); - return -EMSGSIZE; - } - if (dev->type == ARPHRD_ECONET) { /* Real hardware Econet. We're not worthy etc. */ #ifdef CONFIG_ECONET_NATIVE unsigned short proto = 0; int res; + if (len + 15 > dev->mtu) { + mutex_unlock(&econet_mutex); + return -EMSGSIZE; + } + dev_hold(dev); skb = sock_alloc_send_skb(sk, len+LL_ALLOCATED_SPACE(dev), @@ -405,6 +406,11 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, return -ENETDOWN; /* No socket - can't send */ } + if (len > 32768) { + err = -E2BIG; + goto error; + } + /* Make up a UDP datagram and hand it off to some higher intellect. */ memset(&udpdest, 0, sizeof(udpdest)); @@ -436,36 +442,26 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, /* tack our header on the front of the iovec */ size = sizeof(struct aunhdr); - /* - * XXX: that is b0rken. We can't mix userland and kernel pointers - * in iovec, since on a lot of platforms copy_from_user() will - * *not* work with the kernel and userland ones at the same time, - * regardless of what we do with set_fs(). And we are talking about - * econet-over-ethernet here, so "it's only ARM anyway" doesn't - * apply. Any suggestions on fixing that code? -- AV - */ iov[0].iov_base = (void *)&ah; iov[0].iov_len = size; - for (i = 0; i < msg->msg_iovlen; i++) { - void __user *base = msg->msg_iov[i].iov_base; - size_t iov_len = msg->msg_iov[i].iov_len; - /* Check it now since we switch to KERNEL_DS later. */ - if (!access_ok(VERIFY_READ, base, iov_len)) { - mutex_unlock(&econet_mutex); - return -EFAULT; - } - iov[i+1].iov_base = base; - iov[i+1].iov_len = iov_len; - size += iov_len; + + userbuf = vmalloc(len); + if (userbuf == NULL) { + err = -ENOMEM; + goto error; } + iov[1].iov_base = userbuf; + iov[1].iov_len = len; + err = memcpy_fromiovec(userbuf, msg->msg_iov, len); + if (err) + goto error_free_buf; + /* Get a skbuff (no data, just holds our cb information) */ if ((skb = sock_alloc_send_skb(sk, 0, msg->msg_flags & MSG_DONTWAIT, - &err)) == NULL) { - mutex_unlock(&econet_mutex); - return err; - } + &err)) == NULL) + goto error_free_buf; eb = (struct ec_cb *)&skb->cb; @@ -481,7 +477,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, udpmsg.msg_name = (void *)&udpdest; udpmsg.msg_namelen = sizeof(udpdest); udpmsg.msg_iov = &iov[0]; - udpmsg.msg_iovlen = msg->msg_iovlen + 1; + udpmsg.msg_iovlen = 2; udpmsg.msg_control = NULL; udpmsg.msg_controllen = 0; udpmsg.msg_flags=0; @@ -489,9 +485,13 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, oldfs = get_fs(); set_fs(KERNEL_DS); /* More privs :-) */ err = sock_sendmsg(udpsock, &udpmsg, size); set_fs(oldfs); + +error_free_buf: + vfree(userbuf); #else err = -EPROTOTYPE; #endif + error: mutex_unlock(&econet_mutex); return err; -- cgit v1.2.3 From ead0b93a89eb1bab781b1812b42b3cffeecda1d0 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 17 Nov 2010 06:37:16 +0000 Subject: rds: Integer overflow in RDS cmsg handling commit 218854af84038d828a32f061858b1902ed2beec6 upstream. In rds_cmsg_rdma_args(), the user-provided args->nr_local value is restricted to less than UINT_MAX. This seems to need a tighter upper bound, since the calculation of total iov_size can overflow, resulting in a small sock_kmalloc() allocation. This would probably just result in walking off the heap and crashing when calling rds_rdma_pages() with a high count value. If it somehow doesn't crash here, then memory corruption could occur soon after. Signed-off-by: Dan Rosenberg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/rds/rdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/rds/rdma.c b/net/rds/rdma.c index 75fd13bb631b..39989678c2d2 100644 --- a/net/rds/rdma.c +++ b/net/rds/rdma.c @@ -474,7 +474,7 @@ static struct rds_rdma_op *rds_rdma_prepare(struct rds_sock *rs, goto out; } - if (args->nr_local > (u64)UINT_MAX) { + if (args->nr_local > UIO_MAXIOV) { ret = -EMSGSIZE; goto out; } -- cgit v1.2.3 From 3acc1eff9aab5dc224463d6fdc1fc98912f97a6f Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 12 Nov 2010 16:31:23 -0800 Subject: cfg80211: fix extension channel checks to initiate communication commit 9236d838c920e90708570d9bbd7bb82d30a38130 upstream. When operating in a mode that initiates communication and using HT40 we should fail if we cannot use both primary and secondary channels to initiate communication. Our current ht40 allowmap only covers STA mode of operation, for beaconing modes we need a check on the fly as the mode of operation is dynamic and there other flags other than disable which we should read to check if we can initiate communication. Do not allow for initiating communication if our secondary HT40 channel has is either disabled, has a passive scan flag, a no-ibss flag or is a radar channel. Userspace now has similar checks but this is also needed in-kernel. Reported-by: Jouni Malinen Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/wireless/chan.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/net/wireless/chan.c b/net/wireless/chan.c index b01a6f6397d7..93d89d607d5a 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -43,6 +43,36 @@ rdev_freq_to_chan(struct cfg80211_registered_device *rdev, return chan; } +static bool can_beacon_sec_chan(struct wiphy *wiphy, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type) +{ + struct ieee80211_channel *sec_chan; + int diff; + + switch (channel_type) { + case NL80211_CHAN_HT40PLUS: + diff = 20; + case NL80211_CHAN_HT40MINUS: + diff = -20; + default: + return false; + } + + sec_chan = ieee80211_get_channel(wiphy, chan->center_freq + diff); + if (!sec_chan) + return false; + + /* we'll need a DFS capability later */ + if (sec_chan->flags & (IEEE80211_CHAN_DISABLED | + IEEE80211_CHAN_PASSIVE_SCAN | + IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_RADAR)) + return false; + + return true; +} + int cfg80211_set_freq(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, int freq, enum nl80211_channel_type channel_type) @@ -67,6 +97,27 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev, if (!chan) return -EINVAL; + /* Both channels should be able to initiate communication */ + if (wdev && (wdev->iftype == NL80211_IFTYPE_ADHOC || + wdev->iftype == NL80211_IFTYPE_AP || + wdev->iftype == NL80211_IFTYPE_AP_VLAN || + wdev->iftype == NL80211_IFTYPE_MESH_POINT)) { + switch (channel_type) { + case NL80211_CHAN_HT40PLUS: + case NL80211_CHAN_HT40MINUS: + if (!can_beacon_sec_chan(&rdev->wiphy, chan, + channel_type)) { + printk(KERN_DEBUG + "cfg80211: Secondary channel not " + "allowed to initiate communication\n"); + return -EINVAL; + } + break; + default: + break; + } + } + result = rdev->ops->set_channel(&rdev->wiphy, wdev ? wdev->netdev : NULL, chan, channel_type); -- cgit v1.2.3 From d4114d4e08bba51c56d77ee3a3741e98ed107dc5 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 5 Sep 2010 20:04:05 -0700 Subject: r8169: fix rx checksum offload commit adea1ac7effbddbe60a9de6d63462bfe79289e59 upstream. While porting GRO to r8169, I found this driver has a bug in its rx path. All skbs given to network stack had their ip_summed set to CHECKSUM_NONE, while hardware said they had correct TCP/UDP checksums. The reason is driver sets skb->ip_summed on the original skb before the copy eventually done by copybreak. The fresh skb gets the ip_summed = CHECKSUM_NONE value, forcing network stack to recompute checksum, and preventing my GRO patch to work. Fix is to make the ip_summed setting after skb copy. Note : rx_copybreak current value is 16383, so all frames are copied... Signed-off-by: Eric Dumazet Acked-by: Francois Romieu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/r8169.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index ad9833b2ee79..60b591163ae9 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -4458,9 +4458,8 @@ static inline int rtl8169_fragmented_frame(u32 status) return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); } -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) +static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1) { - u32 opts1 = le32_to_cpu(desc->opts1); u32 status = opts1 & RxProtoMask; if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || @@ -4554,8 +4553,6 @@ static int rtl8169_rx_interrupt(struct net_device *dev, continue; } - rtl8169_rx_csum(skb, desc); - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { pci_dma_sync_single_for_device(pdev, addr, pkt_size, PCI_DMA_FROMDEVICE); @@ -4566,6 +4563,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, tp->Rx_skbuff[entry] = NULL; } + rtl8169_rx_csum(skb, status); skb_put(skb, pkt_size); skb->protocol = eth_type_trans(skb, dev); -- cgit v1.2.3 From 6cf6d548763e7e751a3fe77d084999bd11587834 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 20 Oct 2010 22:25:42 +0000 Subject: r8169: (re)init phy on resume commit fccec10b33503a2b1197c8e7a3abd30443bedb08 upstream. Fix switching device to low-speed mode after resume reported in: https://bugzilla.redhat.com/show_bug.cgi?id=502974 Reported-and-tested-by: Laurentiu Badea Signed-off-by: Stanislaw Gruszka Signed-off-by: David S. Miller Cc: Francois Romieu Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/r8169.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 60b591163ae9..661109f7ce49 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -4893,6 +4893,9 @@ static int rtl8169_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct net_device *dev = pci_get_drvdata(pdev); + struct rtl8169_private *tp = netdev_priv(dev); + + rtl8169_init_phy(dev, tp); if (netif_running(dev)) __rtl8169_resume(dev); @@ -4933,6 +4936,8 @@ static int rtl8169_runtime_resume(struct device *device) tp->saved_wolopts = 0; spin_unlock_irq(&tp->lock); + rtl8169_init_phy(dev, tp); + __rtl8169_resume(dev); return 0; -- cgit v1.2.3 From fe590f17c1b2f22e5ce66d091bfb21fe5b59cac0 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Fri, 12 Nov 2010 00:15:25 +0000 Subject: r8169: fix checksum broken commit d5d3ebe3be5c5123f2d444e186717f45284151e2 upstream. If r8196 received packets with invalid sctp/igmp(not tcp, udp) checksum, r8196 set skb->ip_summed wit CHECKSUM_UNNECESSARY. This cause that upper protocol don't check checksum field. I am not family with r8196 driver. I try to guess the meaning of RxProtoIP and IPFail. RxProtoIP stands for received IPv4 packet that upper protocol is not tcp and udp. !(opts1 & IPFail) is true means that driver correctly to check checksum in IPv4 header. If it's right, I think we should not set ip_summed wit CHECKSUM_UNNECESSARY for my sctp packets with invalid checksum. If it's not right, please tell me. Signed-off-by: Shan Wei Acked-by: Francois Romieu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/r8169.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 661109f7ce49..b99dd04710f2 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -4463,8 +4463,7 @@ static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1) u32 status = opts1 & RxProtoMask; if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) + ((status == RxProtoUDP) && !(opts1 & UDPFail))) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb->ip_summed = CHECKSUM_NONE; -- cgit v1.2.3 From 22d2fae507439362ff0efe22fe3196bb9b6e4ce4 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 25 Nov 2010 09:52:45 +0100 Subject: nmi: fix clock comparator revalidation commit e8129c642155616d9e2160a75f103e127c8c3708 upstream. On each machine check all registers are revalidated. The save area for the clock comparator however only contains the upper most seven bytes of the former contents, if valid. Therefore the machine check handler uses a store clock instruction to get the current time and writes that to the clock comparator register which in turn will generate an immediate timer interrupt. However within the lowcore the expected time of the next timer interrupt is stored. If the interrupt happens before that time the handler won't be called. In turn the clock comparator won't be reprogrammed and therefore the interrupt condition stays pending which causes an interrupt loop until the expected time is reached. On NOHZ machines this can result in unresponsive machines since the time of the next expected interrupted can be a couple of days in the future. To fix this just revalidate the clock comparator register with the expected value. In addition the special handling for udelay must be changed as well. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/s390/kernel/nmi.c | 10 ++++------ arch/s390/lib/delay.c | 14 +++++++++----- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c index ac151399ef34..1995c1712fc8 100644 --- a/arch/s390/kernel/nmi.c +++ b/arch/s390/kernel/nmi.c @@ -95,7 +95,6 @@ EXPORT_SYMBOL_GPL(s390_handle_mcck); static int notrace s390_revalidate_registers(struct mci *mci) { int kill_task; - u64 tmpclock; u64 zero; void *fpt_save_area, *fpt_creg_save_area; @@ -214,11 +213,10 @@ static int notrace s390_revalidate_registers(struct mci *mci) : "0", "cc"); #endif /* Revalidate clock comparator register */ - asm volatile( - " stck 0(%1)\n" - " sckc 0(%1)" - : "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory"); - + if (S390_lowcore.clock_comparator == -1) + set_clock_comparator(S390_lowcore.mcck_clock); + else + set_clock_comparator(S390_lowcore.clock_comparator); /* Check if old PSW is valid */ if (!mci->wp) /* diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c index 752b362bf651..7c37ec359ec2 100644 --- a/arch/s390/lib/delay.c +++ b/arch/s390/lib/delay.c @@ -29,17 +29,21 @@ static void __udelay_disabled(unsigned long long usecs) { unsigned long mask, cr0, cr0_saved; u64 clock_saved; + u64 end; + mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT; + end = get_clock() + (usecs << 12); clock_saved = local_tick_disable(); - set_clock_comparator(get_clock() + (usecs << 12)); __ctl_store(cr0_saved, 0, 0); cr0 = (cr0_saved & 0xffff00e0) | 0x00000800; __ctl_load(cr0 , 0, 0); - mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT; lockdep_off(); - trace_hardirqs_on(); - __load_psw_mask(mask); - local_irq_disable(); + do { + set_clock_comparator(end); + trace_hardirqs_on(); + __load_psw_mask(mask); + local_irq_disable(); + } while (get_clock() < end); lockdep_on(); __ctl_load(cr0_saved, 0, 0); local_tick_enable(clock_saved); -- cgit v1.2.3 From 1e6aa82072d3c8267011461d17fbb25c247a3214 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 28 Nov 2010 13:56:09 -0800 Subject: Rename 'pipe_info()' to 'get_pipe_info()' commit 71993e62a47dabddf10302807d6aa260455503f4 upstream. .. and change it to take the 'file' pointer instead of an inode, since that's what all users want anyway. The renaming is preparatory to exporting it to other users. The old 'pipe_info()' name was too generic and is already used elsewhere, so before making the function public we need to use a more specific name. Cc: Jens Axboe Cc: Andrew Morton Cc: Al Viro Cc: Dave Jones Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/splice.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/fs/splice.c b/fs/splice.c index efdbfece9932..8be9d4bf8036 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -1328,12 +1328,11 @@ static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe, * location, so checking ->i_pipe is not enough to verify that this is a * pipe. */ -static inline struct pipe_inode_info *pipe_info(struct inode *inode) +static inline struct pipe_inode_info *get_pipe_info(struct file *file) { - if (S_ISFIFO(inode->i_mode)) - return inode->i_pipe; + struct inode *i = file->f_path.dentry->d_inode; - return NULL; + return S_ISFIFO(i->i_mode) ? i->i_pipe : NULL; } /* @@ -1348,8 +1347,8 @@ static long do_splice(struct file *in, loff_t __user *off_in, loff_t offset, *off; long ret; - ipipe = pipe_info(in->f_path.dentry->d_inode); - opipe = pipe_info(out->f_path.dentry->d_inode); + ipipe = get_pipe_info(in); + opipe = get_pipe_info(out); if (ipipe && opipe) { if (off_in || off_out) @@ -1567,7 +1566,7 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *iov, int error; long ret; - pipe = pipe_info(file->f_path.dentry->d_inode); + pipe = get_pipe_info(file); if (!pipe) return -EBADF; @@ -1654,7 +1653,7 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov, }; long ret; - pipe = pipe_info(file->f_path.dentry->d_inode); + pipe = get_pipe_info(file); if (!pipe) return -EBADF; @@ -2034,8 +2033,8 @@ static int link_pipe(struct pipe_inode_info *ipipe, static long do_tee(struct file *in, struct file *out, size_t len, unsigned int flags) { - struct pipe_inode_info *ipipe = pipe_info(in->f_path.dentry->d_inode); - struct pipe_inode_info *opipe = pipe_info(out->f_path.dentry->d_inode); + struct pipe_inode_info *ipipe = get_pipe_info(in); + struct pipe_inode_info *opipe = get_pipe_info(out); int ret = -EINVAL; /* -- cgit v1.2.3 From 23076bfefeb871c22c40f8abad5b5ea7065a265f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 28 Nov 2010 14:09:57 -0800 Subject: Export 'get_pipe_info()' to other users commit c66fb347946ebdd5b10908866ecc9fa05ee2cf3d upstream. And in particular, use it in 'pipe_fcntl()'. The other pipe functions do not need to use the 'careful' version, since they are only ever called for things that are already known to be pipes. The normal read/write/ioctl functions are called through the file operations structures, so if a file isn't a pipe, they'd never get called. But pipe_fcntl() is special, and called directly from the generic fcntl code, and needs to use the same careful function that the splice code is using. Cc: Jens Axboe Cc: Andrew Morton Cc: Al Viro Cc: Dave Jones Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/pipe.c | 2 +- fs/splice.c | 11 ----------- include/linux/pipe_fs_i.h | 12 ++++++++++++ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/fs/pipe.c b/fs/pipe.c index 37eb1ebeaa90..2665dba3fc22 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -1202,7 +1202,7 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg) struct pipe_inode_info *pipe; long ret; - pipe = file->f_path.dentry->d_inode->i_pipe; + pipe = get_pipe_info(file); if (!pipe) return -EBADF; diff --git a/fs/splice.c b/fs/splice.c index 8be9d4bf8036..188f61aa79c9 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -1323,17 +1323,6 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe, struct pipe_inode_info *opipe, size_t len, unsigned int flags); -/* - * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same - * location, so checking ->i_pipe is not enough to verify that this is a - * pipe. - */ -static inline struct pipe_inode_info *get_pipe_info(struct file *file) -{ - struct inode *i = file->f_path.dentry->d_inode; - - return S_ISFIFO(i->i_mode) ? i->i_pipe : NULL; -} /* * Determine where to splice to/from. diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 445796945ac9..3c5ac3147428 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -161,4 +161,16 @@ void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *); /* for F_SETPIPE_SZ and F_GETPIPE_SZ */ long pipe_fcntl(struct file *, unsigned int, unsigned long arg); +/* + * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same + * location, so checking ->i_pipe is not enough to verify that this is a + * pipe. + */ +static inline struct pipe_inode_info *get_pipe_info(struct file *file) +{ + struct inode *i = file->f_path.dentry->d_inode; + + return S_ISFIFO(i->i_mode) ? i->i_pipe : NULL; +} + #endif -- cgit v1.2.3 From 6efba844d4ad8783c46ee2477344bfd87f737325 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 28 Nov 2010 16:27:19 -0800 Subject: Un-inline get_pipe_info() helper function commit 72083646528d4887b920deb71b37e09bc7d227bb upstream. This avoids some include-file hell, and the function isn't really important enough to be inlined anyway. Reported-by: Ingo Molnar Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/pipe.c | 12 ++++++++++++ include/linux/pipe_fs_i.h | 13 +------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/fs/pipe.c b/fs/pipe.c index 2665dba3fc22..a58d7ee7ad18 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -1197,6 +1197,18 @@ int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf, return ret; } +/* + * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same + * location, so checking ->i_pipe is not enough to verify that this is a + * pipe. + */ +struct pipe_inode_info *get_pipe_info(struct file *file) +{ + struct inode *i = file->f_path.dentry->d_inode; + + return S_ISFIFO(i->i_mode) ? i->i_pipe : NULL; +} + long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg) { struct pipe_inode_info *pipe; diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 3c5ac3147428..bb27d7ec2fb9 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -160,17 +160,6 @@ void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *); /* for F_SETPIPE_SZ and F_GETPIPE_SZ */ long pipe_fcntl(struct file *, unsigned int, unsigned long arg); - -/* - * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same - * location, so checking ->i_pipe is not enough to verify that this is a - * pipe. - */ -static inline struct pipe_inode_info *get_pipe_info(struct file *file) -{ - struct inode *i = file->f_path.dentry->d_inode; - - return S_ISFIFO(i->i_mode) ? i->i_pipe : NULL; -} +struct pipe_inode_info *get_pipe_info(struct file *file); #endif -- cgit v1.2.3 From eb015d662b1831e61ce9610da234565f8349311b Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Mon, 27 Sep 2010 12:30:28 -0400 Subject: Fix pktcdvd ioctl dev_minor range check Upstream 252a52aa4fa22a668f019e55b3aac3ff71ec1c29 The PKT_CTRL_CMD_STATUS device ioctl retrieves a pointer to a pktcdvd_device from the global pkt_devs array. The index into this array is provided directly by the user and is a signed integer, so the comparison to ensure that it falls within the bounds of this array will fail when provided with a negative index. This can be used to read arbitrary kernel memory or cause a crash due to an invalid pointer dereference. This can be exploited by users with permission to open /dev/pktcdvd/control (on many distributions, this is readable by group "cdrom"). Signed-off-by: Dan Rosenberg [ Rather than add a cast, just make the function take the right type -Linus ] Signed-off-by: Linus Torvalds Signed-off-by: Andi Kleen --- drivers/block/pktcdvd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 8a549db2aa78..8403fd54cadb 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2368,7 +2368,7 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush) pkt_shrink_pktlist(pd); } -static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor) +static struct pktcdvd_device *pkt_find_dev_from_minor(unsigned int dev_minor) { if (dev_minor >= MAX_WRITERS) return NULL; -- cgit v1.2.3 From 787a4575ad364d69416615881345eae389882588 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 14 Dec 2010 23:40:18 +0100 Subject: Release 2.6.35.10 Signed-off-by: Andi Kleen --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 90ba786b757c..653850194d1b 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 35 -EXTRAVERSION = .9 +EXTRAVERSION = .10 NAME = Yokohama # *DOCUMENTATION* -- cgit v1.2.3 From 79c6d16d8a4e355902861a9599630b7077a82d0e Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 10 Dec 2010 23:55:22 -0500 Subject: x86, hotplug: Use mwait to offline a processor, fix the legacy case upstream ea53069231f9317062910d6e772cca4ce93de8c8 x86, hotplug: Use mwait to offline a processor, fix the legacy case Here included also some small follow-on patches to the same code: upstream a68e5c94f7d3dd64fef34dd5d97e365cae4bb42a x86, hotplug: Move WBINVD back outside the play_dead loop upstream ce5f68246bf2385d6174856708d0b746dc378f20 x86, hotplug: In the MWAIT case of play_dead, CLFLUSH the cache line https://bugzilla.kernel.org/show_bug.cgi?id=5471 Signed-off-by: H. Peter Anvin Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/include/asm/processor.h | 23 ----------- arch/x86/kernel/smpboot.c | 85 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 24 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 7e5c6a60b8ee..eccaebc632d1 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -763,29 +763,6 @@ extern unsigned long boot_option_idle_override; extern unsigned long idle_halt; extern unsigned long idle_nomwait; -/* - * on systems with caches, caches must be flashed as the absolute - * last instruction before going into a suspended halt. Otherwise, - * dirty data can linger in the cache and become stale on resume, - * leading to strange errors. - * - * perform a variety of operations to guarantee that the compiler - * will not reorder instructions. wbinvd itself is serializing - * so the processor will not reorder. - * - * Systems without cache can just go into halt. - */ -static inline void wbinvd_halt(void) -{ - mb(); - /* check for clflush to determine if wbinvd is legal */ - if (cpu_has_clflush) - asm volatile("cli; wbinvd; 1: hlt; jmp 1b" : : : "memory"); - else - while (1) - halt(); -} - extern void enable_sep_cpu(void); extern int sysenter_setup(void); diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 821ee1b7634e..40eb0f94e8c5 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1387,11 +1387,94 @@ void play_dead_common(void) local_irq_disable(); } +#define MWAIT_SUBSTATE_MASK 0xf +#define MWAIT_SUBSTATE_SIZE 4 + +#define CPUID_MWAIT_LEAF 5 +#define CPUID5_ECX_EXTENSIONS_SUPPORTED 0x1 + +/* + * We need to flush the caches before going to sleep, lest we have + * dirty data in our caches when we come back up. + */ +static inline void mwait_play_dead(void) +{ + unsigned int eax, ebx, ecx, edx; + unsigned int highest_cstate = 0; + unsigned int highest_subcstate = 0; + int i; + void *mwait_ptr; + + if (!cpu_has(¤t_cpu_data, X86_FEATURE_MWAIT)) + return; + if (!cpu_has(¤t_cpu_data, X86_FEATURE_CLFLSH)) + return; + if (current_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) + return; + + eax = CPUID_MWAIT_LEAF; + ecx = 0; + native_cpuid(&eax, &ebx, &ecx, &edx); + + /* + * eax will be 0 if EDX enumeration is not valid. + * Initialized below to cstate, sub_cstate value when EDX is valid. + */ + if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED)) { + eax = 0; + } else { + edx >>= MWAIT_SUBSTATE_SIZE; + for (i = 0; i < 7 && edx; i++, edx >>= MWAIT_SUBSTATE_SIZE) { + if (edx & MWAIT_SUBSTATE_MASK) { + highest_cstate = i; + highest_subcstate = edx & MWAIT_SUBSTATE_MASK; + } + } + eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) | + (highest_subcstate - 1); + } + + /* + * This should be a memory location in a cache line which is + * unlikely to be touched by other processors. The actual + * content is immaterial as it is not actually modified in any way. + */ + mwait_ptr = ¤t_thread_info()->flags; + + wbinvd(); + + while (1) { + /* + * The CLFLUSH is a workaround for erratum AAI65 for + * the Xeon 7400 series. It's not clear it is actually + * needed, but it should be harmless in either case. + * The WBINVD is insufficient due to the spurious-wakeup + * case where we return around the loop. + */ + clflush(mwait_ptr); + __monitor(mwait_ptr, 0, 0); + mb(); + __mwait(eax, 0); + } +} + +static inline void hlt_play_dead(void) +{ + if (current_cpu_data.x86 >= 4) + wbinvd(); + + while (1) { + native_halt(); + } +} + void native_play_dead(void) { play_dead_common(); tboot_shutdown(TB_SHUTDOWN_WFS); - wbinvd_halt(); + + mwait_play_dead(); /* Only returns on failure */ + hlt_play_dead(); } #else /* ... !CONFIG_HOTPLUG_CPU */ -- cgit v1.2.3 From 84e4371b03088be955408911af51904c66a5b43e Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 30 Nov 2010 16:39:27 +0100 Subject: fuse: verify ioctl retries commit 7572777eef78ebdee1ecb7c258c0ef94d35bad16 upstream. Verify that the total length of the iovec returned in FUSE_IOCTL_RETRY doesn't overflow iov_length(). Signed-off-by: Miklos Szeredi Signed-off-by: Andi Kleen CC: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/fuse/file.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index fcd36797e6cb..112e631128f0 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1627,6 +1627,20 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov, return 0; } +/* Make sure iov_length() won't overflow */ +static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count) +{ + size_t n; + u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT; + + for (n = 0; n < count; n++) { + if (iov->iov_len > (size_t) max) + return -ENOMEM; + max -= iov->iov_len; + } + return 0; +} + /* * For ioctls, there is no generic way to determine how much memory * needs to be read and/or written. Furthermore, ioctls are allowed @@ -1820,6 +1834,14 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, in_iov = page_address(iov_page); out_iov = in_iov + in_iovs; + err = fuse_verify_ioctl_iov(in_iov, in_iovs); + if (err) + goto out; + + err = fuse_verify_ioctl_iov(out_iov, out_iovs); + if (err) + goto out; + goto retry; } -- cgit v1.2.3 From 986afbde0f1dde7695987fd2458f9676ce0389aa Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 30 Nov 2010 16:39:27 +0100 Subject: fuse: fix ioctl when server is 32bit commit d9d318d39dd5cb686660504a3565aac453709ccc upstream. If a 32bit CUSE server is run on 64bit this results in EIO being returned to the caller. The reason is that FUSE_IOCTL_RETRY reply was defined to use 'struct iovec', which is different on 32bit and 64bit archs. Work around this by looking at the size of the reply to determine which struct was used. This is only needed if CONFIG_COMPAT is defined. A more permanent fix for the interface will be to use the same struct on both 32bit and 64bit. Reported-by: "ccmail111" Signed-off-by: Miklos Szeredi Signed-off-by: Andi Kleen CC: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/fuse/file.c | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 112e631128f0..f6c333ffa244 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -13,6 +13,7 @@ #include #include #include +#include static const struct file_operations fuse_direct_io_file_operations; @@ -1641,6 +1642,44 @@ static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count) return 0; } +/* + * CUSE servers compiled on 32bit broke on 64bit kernels because the + * ABI was defined to be 'struct iovec' which is different on 32bit + * and 64bit. Fortunately we can determine which structure the server + * used from the size of the reply. + */ +static int fuse_copy_ioctl_iovec(struct iovec *dst, void *src, + size_t transferred, unsigned count, + bool is_compat) +{ +#ifdef CONFIG_COMPAT + if (count * sizeof(struct compat_iovec) == transferred) { + struct compat_iovec *ciov = src; + unsigned i; + + /* + * With this interface a 32bit server cannot support + * non-compat (i.e. ones coming from 64bit apps) ioctl + * requests + */ + if (!is_compat) + return -EINVAL; + + for (i = 0; i < count; i++) { + dst[i].iov_base = compat_ptr(ciov[i].iov_base); + dst[i].iov_len = ciov[i].iov_len; + } + return 0; + } +#endif + + if (count * sizeof(struct iovec) != transferred) + return -EIO; + + memcpy(dst, src, transferred); + return 0; +} + /* * For ioctls, there is no generic way to determine how much memory * needs to be read and/or written. Furthermore, ioctls are allowed @@ -1822,14 +1861,13 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, in_iovs + out_iovs > FUSE_IOCTL_MAX_IOV) goto out; - err = -EIO; - if ((in_iovs + out_iovs) * sizeof(struct iovec) != transferred) - goto out; - - /* okay, copy in iovs and retry */ vaddr = kmap_atomic(pages[0], KM_USER0); - memcpy(page_address(iov_page), vaddr, transferred); + err = fuse_copy_ioctl_iovec(page_address(iov_page), vaddr, + transferred, in_iovs + out_iovs, + (flags & FUSE_IOCTL_COMPAT) != 0); kunmap_atomic(vaddr, KM_USER0); + if (err) + goto out; in_iov = page_address(iov_page); out_iov = in_iov + in_iovs; -- cgit v1.2.3 From 400d406b0a8c576002c2bc48e0d956ef613c68a3 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Thu, 9 Dec 2010 07:17:27 +0100 Subject: ALSA: HDA: Quirk for Dell Vostro 320 to make microphone work commit 8a96b1e02029aa512199b1b6d281dcede9ed81f1 upstream. BugLink: http://launchpad.net/497546 Confirmed that the ideapad model works better than the current quirk for Dell Vostro 320. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_conexant.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 53418b490290..eff443ff9edd 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3026,8 +3026,7 @@ static const char *cxt5066_models[CXT5066_MODELS] = { static struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", CXT5066_LAPTOP), - SND_PCI_QUIRK(0x1028, 0x02f5, "Dell", - CXT5066_DELL_LAPTOP), + SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTO), SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), -- cgit v1.2.3 From f035aa4f932e2d589e3b7dc47e6043c2651bd443 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Sun, 5 Dec 2010 08:43:14 -0500 Subject: ALSA: hda: Use position_fix=1 for Acer Aspire 5538 to enable capture on internal mic commit dd5a089edfa51a74692604b4b427953d8e16bc35 upstream. BugLink: https://launchpad.net/bugs/685161 The reporter of the bug states that he must use position_fix=1 to enable capture for the internal microphone, so set it for his machine's PCI SSID. Verified using 2.6.35 and the 2010-12-04 alsa-driver build. Reported-and-tested-by: Ralph Wabel Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/hda_intel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index d83cc563e468..a5f6774b630f 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2291,6 +2291,7 @@ static int azx_dev_free(struct snd_device *device) */ static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1025, 0x009f, "Acer Aspire 5110", POS_FIX_LPIB), + SND_PCI_QUIRK(0x1025, 0x026f, "Acer Aspire 5538", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB), -- cgit v1.2.3 From b3a33e333ac922458e5b662990a6d17f7510dd52 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Thu, 2 Dec 2010 22:45:45 -0500 Subject: ALSA: hda: Use model=lg quirk for LG P1 Express to enable playback and capture commit 77c4d5cdb81d25a45fbdfb84dd3348121219a072 upstream. BugLink: https://launchpad.net/bugs/595482 The original reporter states that audible playback from the internal speaker is inaudible despite the hardware being properly detected. To work around this symptom, he uses the model=lg quirk to properly enable both playback, capture, and jack sense. Another user corroborates this workaround on separate hardware. Add this PCI SSID to the quirk table to enable it for further LG P1 Expresses. Reported-and-tested-by: Philip Peitsch Tested-by: nikhov Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a074c8e5f23b..b6b59a577f6c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4240,6 +4240,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU), SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW), SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG), + SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG), SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG), SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW), SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700), -- cgit v1.2.3 From 099433591bd86e532987a4e481fe351c4237386e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 8 Dec 2010 10:05:34 -0500 Subject: drm/radeon/kms: don't apply 7xx HDP flush workaround on AGP commit f3886f85cfde578f1d0ba6e40ac5f9d70043923b upstream. It should be required for all 7xx asics, but seems to cause problems on some AGP 7xx chips. Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=19002 Signed-off-by: Alex Deucher Signed-off-by: Andi Kleen Reported-and-Tested-by: Duncan <1i5t5.duncan@cox.net> Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/r600.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index a40be952554a..6356b1c55479 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -869,12 +869,15 @@ void r600_pcie_gart_tlb_flush(struct radeon_device *rdev) u32 tmp; /* flush hdp cache so updates hit vram */ - if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) { + if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) && + !(rdev->flags & RADEON_IS_AGP)) { void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; u32 tmp; /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL + * This seems to cause problems on some AGP cards. Just use the old + * method for them. */ WREG32(HDP_DEBUG1, 0); tmp = readl((void __iomem *)ptr); @@ -3523,10 +3526,12 @@ int r600_debugfs_mc_info_init(struct radeon_device *rdev) void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo) { /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read - * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL + * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL. + * This seems to cause problems on some AGP cards. Just use the old + * method for them. */ if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) && - rdev->vram_scratch.ptr) { + rdev->vram_scratch.ptr && !(rdev->flags & RADEON_IS_AGP)) { void __iomem *ptr = (void *)rdev->vram_scratch.ptr; u32 tmp; -- cgit v1.2.3 From 6b3a20cdc30067b8825c7f773a3b0b16cb56ed21 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 8 Dec 2010 19:09:42 -0500 Subject: drm/kms: remove spaces from connector names (v2) commit e76116ca9671e2e5239054a40303b94feab585ad upstream. Grub doesn't parse spaces in parameters correctly, so this makes it impossible to force video= parameters for kms on the grub kernel command line. v2: shorten the names to make them easier to type. Reported-by: Sergej Pupykin Cc: Sergej Pupykin Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/drm_crtc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 57cea01c4ffb..5f32f7205e11 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -155,12 +155,12 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 }, { DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 }, { DRM_MODE_CONNECTOR_Component, "Component", 0 }, - { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN", 0 }, - { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort", 0 }, - { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 }, - { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 }, + { DRM_MODE_CONNECTOR_9PinDIN, "DIN", 0 }, + { DRM_MODE_CONNECTOR_DisplayPort, "DP", 0 }, + { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A", 0 }, + { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 }, { DRM_MODE_CONNECTOR_TV, "TV", 0 }, - { DRM_MODE_CONNECTOR_eDP, "Embedded DisplayPort", 0 }, + { DRM_MODE_CONNECTOR_eDP, "eDP", 0 }, }; static struct drm_prop_enum_list drm_encoder_enum_list[] = -- cgit v1.2.3 From e3e8f697884d634e45e31734bc16d20a45452cb6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 3 Dec 2010 14:37:22 -0500 Subject: drm/radeon/kms: fix vram base calculation on rs780/rs880 commit 8961d52d4cc52edf5672f8f2712c57162b736793 upstream. Avoid overflowing a 32 bit value. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/r600.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 6356b1c55479..cdddc4d4063a 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1189,8 +1189,10 @@ void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) mc->vram_end, mc->real_vram_size >> 20); } else { u64 base = 0; - if (rdev->flags & RADEON_IS_IGP) - base = (RREG32(MC_VM_FB_LOCATION) & 0xFFFF) << 24; + if (rdev->flags & RADEON_IS_IGP) { + base = RREG32(MC_VM_FB_LOCATION) & 0xFFFF; + base <<= 24; + } radeon_vram_location(rdev, &rdev->mc, base); rdev->mc.gtt_base_align = 0; radeon_gtt_location(rdev, mc); -- cgit v1.2.3 From 027f49d5bf115eab63c9ef504a76c1a9711fca66 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 26 Nov 2010 13:00:59 +0100 Subject: nohz: Fix printk_needs_cpu() return value on offline cpus commit 61ab25447ad6334a74e32f60efb135a3467223f8 upstream. This patch fixes a hang observed with 2.6.32 kernels where timers got enqueued on offline cpus. printk_needs_cpu() may return 1 if called on offline cpus. When a cpu gets offlined it schedules the idle process which, before killing its own cpu, will call tick_nohz_stop_sched_tick(). That function in turn will call printk_needs_cpu() in order to check if the local tick can be disabled. On offline cpus this function should naturally return 0 since regardless if the tick gets disabled or not the cpu will be dead short after. That is besides the fact that __cpu_disable() should already have made sure that no interrupts on the offlined cpu will be delivered anyway. In this case it prevents tick_nohz_stop_sched_tick() to call select_nohz_load_balancer(). No idea if that really is a problem. However what made me debug this is that on 2.6.32 the function get_nohz_load_balancer() is used within __mod_timer() to select a cpu on which a timer gets enqueued. If printk_needs_cpu() returns 1 then the nohz_load_balancer cpu doesn't get updated when a cpu gets offlined. It may contain the cpu number of an offline cpu. In turn timers get enqueued on an offline cpu and not very surprisingly they never expire and cause system hangs. This has been observed 2.6.32 kernels. On current kernels __mod_timer() uses get_nohz_timer_target() which doesn't have that problem. However there might be other problems because of the too early exit tick_nohz_stop_sched_tick() in case a cpu goes offline. Easiest way to fix this is just to test if the current cpu is offline and call printk_tick() directly which clears the condition. Alternatively I tried a cpu hotplug notifier which would clear the condition, however between calling the notifier function and printk_needs_cpu() something could have called printk() again and the problem is back again. This seems to be the safest fix. Signed-off-by: Heiko Carstens Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <20101126120235.406766476@de.ibm.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/printk.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/printk.c b/kernel/printk.c index 444b770c9595..ea64cb5dd0ba 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -1034,6 +1034,8 @@ void printk_tick(void) int printk_needs_cpu(int cpu) { + if (unlikely(cpu_is_offline(cpu))) + printk_tick(); return per_cpu(printk_pending, cpu); } -- cgit v1.2.3 From 8a1e3d609bb1b445e34b8bc05ac87de89c4483e8 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 1 Dec 2010 10:11:09 +0100 Subject: nohz: Fix get_next_timer_interrupt() vs cpu hotplug commit dbd87b5af055a0cc9bba17795c9a2b0d17795389 upstream. This fixes a bug as seen on 2.6.32 based kernels where timers got enqueued on offline cpus. If a cpu goes offline it might still have pending timers. These will be migrated during CPU_DEAD handling after the cpu is offline. However while the cpu is going offline it will schedule the idle task which will then call tick_nohz_stop_sched_tick(). That function in turn will call get_next_timer_intterupt() to figure out if the tick of the cpu can be stopped or not. If it turns out that the next tick is just one jiffy off (delta_jiffies == 1) tick_nohz_stop_sched_tick() incorrectly assumes that the tick should not stop and takes an early exit and thus it won't update the load balancer cpu. Just afterwards the cpu will be killed and the load balancer cpu could be the offline cpu. On 2.6.32 based kernel get_nohz_load_balancer() gets called to decide on which cpu a timer should be enqueued (see __mod_timer()). Which leads to the possibility that timers get enqueued on an offline cpu. These will never expire and can cause a system hang. This has been observed 2.6.32 kernels. On current kernels __mod_timer() uses get_nohz_timer_target() which doesn't have that problem. However there might be other problems because of the too early exit tick_nohz_stop_sched_tick() in case a cpu goes offline. The easiest and probably safest fix seems to be to let get_next_timer_interrupt() just lie and let it say there isn't any pending timer if the current cpu is offline. I also thought of moving migrate_[hr]timers() from CPU_DEAD to CPU_DYING, but seeing that there already have been fixes at least in the hrtimer code in this area I'm afraid that this could add new subtle bugs. Signed-off-by: Heiko Carstens Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <20101201091109.GA8984@osiris.boeblingen.de.ibm.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/timer.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/timer.c b/kernel/timer.c index ee305c8d4e18..14f13e9c8dc7 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1237,6 +1237,12 @@ unsigned long get_next_timer_interrupt(unsigned long now) struct tvec_base *base = __get_cpu_var(tvec_bases); unsigned long expires; + /* + * Pretend that there is no timer pending if the cpu is offline. + * Possible pending timers will be migrated later to an active cpu. + */ + if (cpu_is_offline(smp_processor_id())) + return now + NEXT_TIMER_MAX_DELTA; spin_lock(&base->lock); if (time_before_eq(base->next_timer, base->timer_jiffies)) base->next_timer = __next_timer_interrupt(base); -- cgit v1.2.3 From cdda0cb15d14a9c49c337e0bb9b69a392290016d Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 10 Dec 2010 12:31:14 -0500 Subject: NFS: Fix panic after nfs_umount() commit 5b362ac3799ff4225c40935500f520cad4d7ed66 upstream. After a few unsuccessful NFS mount attempts in which the client and server cannot agree on an authentication flavor both support, the client panics. nfs_umount() is invoked in the kernel in this case. Turns out nfs_umount()'s UMNT RPC invocation causes the RPC client to write off the end of the rpc_clnt's iostat array. This is because the mount client's nrprocs field is initialized with the count of defined procedures (two: MNT and UMNT), rather than the size of the client's proc array (four). The fix is to use the same initialization technique used by most other upper layer clients in the kernel. Introduced by commit 0b524123, which failed to update nrprocs when support was added for UMNT in the kernel. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=24302 BugLink: http://bugs.launchpad.net/bugs/683938 Reported-by: Stefan Bader Tested-by: Stefan Bader Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfs/mount_clnt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 59047f8d7d72..3dde50c093b5 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c @@ -503,13 +503,13 @@ static struct rpc_procinfo mnt3_procedures[] = { static struct rpc_version mnt_version1 = { .number = 1, - .nrprocs = 2, + .nrprocs = ARRAY_SIZE(mnt_procedures), .procs = mnt_procedures, }; static struct rpc_version mnt_version3 = { .number = 3, - .nrprocs = 2, + .nrprocs = ARRAY_SIZE(mnt3_procedures), .procs = mnt3_procedures, }; -- cgit v1.2.3 From 74526c3deda36c784c87ba977550234a95ecbb05 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Thu, 2 Dec 2010 11:14:30 +1100 Subject: nfsd: Fix possible BUG_ON firing in set_change_info commit c1ac3ffcd0bc7e9617f62be8c7043d53ab84deac upstream. If vfs_getattr in fill_post_wcc returns an error, we don't set fh_post_change. For NFSv4, this can result in set_change_info triggering a BUG_ON. i.e. fh_post_saved being zero isn't really a bug. So: - instead of BUGging when fh_post_saved is zero, just clear ->atomic. - if vfs_getattr fails in fill_post_wcc, take a copy of i_ctime anyway. This will be used i seg_change_info, but not overly trusted. - While we are there, remove the pointless 'if' statements in set_change_info. There is no harm setting all the values. Signed-off-by: NeilBrown Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfsd/nfs3xdr.c | 6 ++++-- fs/nfsd/xdr4.h | 21 ++++++++++----------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 2a533a0af2a9..7e84a852cdae 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -260,9 +260,11 @@ void fill_post_wcc(struct svc_fh *fhp) err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry, &fhp->fh_post_attr); fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version; - if (err) + if (err) { fhp->fh_post_saved = 0; - else + /* Grab the ctime anyway - set_change_info might use it */ + fhp->fh_post_attr.ctime = fhp->fh_dentry->d_inode->i_ctime; + } else fhp->fh_post_saved = 1; } diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 4d476ff08ae6..60fce3dc5cb5 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h @@ -484,18 +484,17 @@ static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp) static inline void set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp) { - BUG_ON(!fhp->fh_pre_saved || !fhp->fh_post_saved); - cinfo->atomic = 1; + BUG_ON(!fhp->fh_pre_saved); + cinfo->atomic = fhp->fh_post_saved; cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode); - if (cinfo->change_supported) { - cinfo->before_change = fhp->fh_pre_change; - cinfo->after_change = fhp->fh_post_change; - } else { - cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec; - cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec; - cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec; - cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec; - } + + cinfo->before_change = fhp->fh_pre_change; + cinfo->after_change = fhp->fh_post_change; + cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec; + cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec; + cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec; + cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec; + } int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *); -- cgit v1.2.3 From 2341d3c4085fb6d075d6e146c0093f277396249f Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Sun, 28 Nov 2010 21:04:05 +0000 Subject: NFS: Fix fcntl F_GETLK not reporting some conflicts commit 21ac19d484a8ffb66f64487846c8d53afef04d2b upstream. The commit 129a84de2347002f09721cda3155ccfd19fade40 (locks: fix F_GETLK regression (failure to find conflicts)) fixed the posix_test_lock() function by itself, however, its usage in NFS changed by the commit 9d6a8c5c213e34c475e72b245a8eb709258e968c (locks: give posix_test_lock same interface as ->lock) remained broken - subsequent NFS-specific locking code received F_UNLCK instead of the user-specified lock type. To fix the problem, fl->fl_type needs to be saved before the posix_test_lock() call and restored if no local conflicts were reported. Reference: https://bugzilla.kernel.org/show_bug.cgi?id=23892 Tested-by: Alexander Morozov Signed-off-by: Sergey Vlasov Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfs/file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index e8929eeb9e5a..642c819c89cd 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -696,6 +696,7 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) { struct inode *inode = filp->f_mapping->host; int status = 0; + unsigned int saved_type = fl->fl_type; /* Try local locking first */ posix_test_lock(filp, fl); @@ -703,6 +704,7 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) /* found a conflict */ goto out; } + fl->fl_type = saved_type; if (nfs_have_delegation(inode, FMODE_READ)) goto out_noconflict; -- cgit v1.2.3 From 33d4654fd103c1eb2a203074b14d8cd1a584ace7 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 16 Nov 2010 16:55:19 +1100 Subject: sunrpc: prevent use-after-free on clearing XPT_BUSY commit ed2849d3ecfa339435818eeff28f6c3424300cec upstream. When an xprt is created, it has a refcount of 1, and XPT_BUSY is set. The refcount is *not* owned by the thread that created the xprt (as is clear from the fact that creators never put the reference). Rather, it is owned by the absence of XPT_DEAD. Once XPT_DEAD is set, (And XPT_BUSY is clear) that initial reference is dropped and the xprt can be freed. So when a creator clears XPT_BUSY it is dropping its only reference and so must not touch the xprt again. However svc_recv, after calling ->xpo_accept (and so getting an XPT_BUSY reference on a new xprt), calls svc_xprt_recieved. This clears XPT_BUSY and then svc_xprt_enqueue - this last without owning a reference. This is dangerous and has been seen to leave svc_xprt_enqueue working with an xprt containing garbage. So we need to hold an extra counted reference over that call to svc_xprt_received. For safety, any time we clear XPT_BUSY and then use the xprt again, we first get a reference, and the put it again afterwards. Note that svc_close_all does not need this extra protection as there are no threads running, and the final free can only be called asynchronously from such a thread. Signed-off-by: NeilBrown Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/sunrpc/svc_xprt.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index cbc084939dd8..2f5fb71854d3 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -212,6 +212,7 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, spin_lock(&svc_xprt_class_lock); list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) { struct svc_xprt *newxprt; + unsigned short newport; if (strcmp(xprt_name, xcl->xcl_name)) continue; @@ -230,8 +231,9 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, spin_lock_bh(&serv->sv_lock); list_add(&newxprt->xpt_list, &serv->sv_permsocks); spin_unlock_bh(&serv->sv_lock); + newport = svc_xprt_local_port(newxprt); clear_bit(XPT_BUSY, &newxprt->xpt_flags); - return svc_xprt_local_port(newxprt); + return newport; } err: spin_unlock(&svc_xprt_class_lock); @@ -431,8 +433,13 @@ void svc_xprt_received(struct svc_xprt *xprt) { BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags)); xprt->xpt_pool = NULL; + /* As soon as we clear busy, the xprt could be closed and + * 'put', so we need a reference to call svc_xprt_enqueue with: + */ + svc_xprt_get(xprt); clear_bit(XPT_BUSY, &xprt->xpt_flags); svc_xprt_enqueue(xprt); + svc_xprt_put(xprt); } EXPORT_SYMBOL_GPL(svc_xprt_received); -- cgit v1.2.3 From 998bd06665b1c8e1abb8c99c96f6db4103b793e4 Mon Sep 17 00:00:00 2001 From: Gabriele Gorla Date: Wed, 8 Dec 2010 16:27:22 +0100 Subject: hwmon: (adm1026) Allow 1 as a valid divider value commit 8b0f1840a46449e1946fc88860ef3ec8d6b1c2c7 upstream. Allow 1 as a valid div value as specified in the ADM1026 datasheet. Signed-off-by: Gabriele Gorla Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/hwmon/adm1026.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index 65335b268fa9..e059a5f8025d 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -920,9 +920,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, val = simple_strtol(buf, NULL, 10); new_div = DIV_TO_REG(val); - if (new_div == 0) { - return -EINVAL; - } + mutex_lock(&data->update_lock); orig_div = data->fan_div[nr]; data->fan_div[nr] = DIV_FROM_REG(new_div); -- cgit v1.2.3 From 61ae3863b6d326bf6b24cb24ceb59025dbdf4d52 Mon Sep 17 00:00:00 2001 From: Gabriele Gorla Date: Wed, 8 Dec 2010 16:27:22 +0100 Subject: hwmon: (adm1026) Fix setting fan_div commit 52bc9802ce849d0d287cc5fe76d06b0daa3986ca upstream. Prevent setting fan_div from stomping on other fans that share the same I2C register. Signed-off-by: Gabriele Gorla Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/hwmon/adm1026.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index e059a5f8025d..9975bbfb1b31 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -916,7 +916,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, int nr = sensor_attr->index; struct i2c_client *client = to_i2c_client(dev); struct adm1026_data *data = i2c_get_clientdata(client); - int val, orig_div, new_div, shift; + int val, orig_div, new_div; val = simple_strtol(buf, NULL, 10); new_div = DIV_TO_REG(val); @@ -926,15 +926,17 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, data->fan_div[nr] = DIV_FROM_REG(new_div); if (nr < 4) { /* 0 <= nr < 4 */ - shift = 2 * nr; adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3, - ((DIV_TO_REG(orig_div) & (~(0x03 << shift))) | - (new_div << shift))); + (DIV_TO_REG(data->fan_div[0]) << 0) | + (DIV_TO_REG(data->fan_div[1]) << 2) | + (DIV_TO_REG(data->fan_div[2]) << 4) | + (DIV_TO_REG(data->fan_div[3]) << 6)); } else { /* 3 < nr < 8 */ - shift = 2 * (nr - 4); adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7, - ((DIV_TO_REG(orig_div) & (~(0x03 << (2 * shift)))) | - (new_div << shift))); + (DIV_TO_REG(data->fan_div[4]) << 0) | + (DIV_TO_REG(data->fan_div[5]) << 2) | + (DIV_TO_REG(data->fan_div[6]) << 4) | + (DIV_TO_REG(data->fan_div[7]) << 6)); } if (data->fan_div[nr] != orig_div) { -- cgit v1.2.3 From 96c72bbe72854a8680cf3a03e3bf027e8eb7ef55 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 2 Dec 2010 17:48:35 +0100 Subject: EDAC: Fix workqueue-related crashes commit bb31b3122c0dd07d2d958da17a50ad771ce79e2b upstream. 00740c58541b6087d78418cebca1fcb86dc6077d changed edac_core to un-/register a workqueue item only if a lowlevel driver supplies a polling routine. Normally, when we remove a polling low-level driver, we go and cancel all the queued work. However, the workqueue unreg happens based on the ->op_state setting, and edac_mc_del_mc() sets this to OP_OFFLINE _before_ we cancel the work item, leading to NULL ptr oops on the workqueue list. Fix it by putting the unreg stuff in proper order. Reported-and-tested-by: Tobias Karnat LKML-Reference: <1291201307.3029.21.camel@Tobias-Karnat> Signed-off-by: Borislav Petkov Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/edac/edac_mc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 3630308e7b81..11c095d47cb1 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -575,14 +575,16 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev) return NULL; } - /* marking MCI offline */ - mci->op_state = OP_OFFLINE; - del_mc_from_global_list(mci); mutex_unlock(&mem_ctls_mutex); - /* flush workq processes and remove sysfs */ + /* flush workq processes */ edac_mc_workq_teardown(mci); + + /* marking MCI offline */ + mci->op_state = OP_OFFLINE; + + /* remove from sysfs */ edac_remove_sysfs_mci_device(mci); edac_printk(KERN_INFO, EDAC_MC, -- cgit v1.2.3 From e4e576308d04c71d1f68e8896daeb5f49afd7ff2 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 6 Dec 2010 16:20:25 +0100 Subject: amd64_edac: Fix interleaving check commit e726f3c368e7c1919a7166ec09c5705759f1a69d upstream. When matching error address to the range contained by one memory node, we're in valid range when node interleaving 1. is disabled, or 2. enabled and when the address bits we interleave on match the interleave selector on this node (see the "Node Interleaving" section in the BKDG for an enlightening example). Thus, when we early-exit, we need to reverse the compound logic statement properly. Signed-off-by: Borislav Petkov Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/edac/amd64_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index c20a6c925bbe..0e035063f26a 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1567,7 +1567,7 @@ static int f10_match_to_this_node(struct amd64_pvt *pvt, int dram_range, debugf1(" HoleOffset=0x%x HoleValid=0x%x IntlvSel=0x%x\n", hole_off, hole_valid, intlv_sel); - if (intlv_en || + if (intlv_en && (intlv_sel != ((sys_addr >> 12) & intlv_en))) return -EINVAL; -- cgit v1.2.3 From 4aaf959ea379034a6b010be9c3acc88a14f97642 Mon Sep 17 00:00:00 2001 From: Uk Kim Date: Sun, 5 Dec 2010 17:26:07 +0900 Subject: ASoC: Fix swap of left and right channels for WM8993/4 speaker boost gain commit ed8cc471d75365f8590c76f580def899d58028c0 upstream. SPKOUTL_BOOST start from third bit, SPKOUTLR_BOOST start from 0 bit. Signed-off-by: Uk Kim Acked-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/soc/codecs/wm_hubs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 16f1a57da08a..20ffd28abcd9 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -293,7 +293,7 @@ SOC_DOUBLE_R("Speaker Switch", SOC_DOUBLE_R("Speaker ZC Switch", WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT, 7, 1, 0), -SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 0, 3, 7, 0, +SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 3, 0, 7, 0, spkboost_tlv), SOC_ENUM("Speaker Reference", speaker_ref), SOC_ENUM("Speaker Mode", speaker_mode), -- cgit v1.2.3 From 1c33da96e2e2b6c4994367d7a4702db566ccd428 Mon Sep 17 00:00:00 2001 From: Uk Kim Date: Sun, 5 Dec 2010 17:32:16 +0900 Subject: ASoC: Fix off by one error in WM8994 EQ register bank size commit 3fcc0afbb9c93f3599ba03273e59915670b6c2c2 upstream. Signed-off-by: Uk Kim Acked-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/linux/mfd/wm8994/pdata.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h index 5c51f367c061..add8a1b8bcf0 100644 --- a/include/linux/mfd/wm8994/pdata.h +++ b/include/linux/mfd/wm8994/pdata.h @@ -29,7 +29,7 @@ struct wm8994_ldo_pdata { #define WM8994_CONFIGURE_GPIO 0x8000 #define WM8994_DRC_REGS 5 -#define WM8994_EQ_REGS 19 +#define WM8994_EQ_REGS 20 /** * DRC configurations are specified with a label and a set of register -- cgit v1.2.3 From 92ba39dad3910e43309686bd978d2f3e7a953281 Mon Sep 17 00:00:00 2001 From: Seungwhan Youn Date: Thu, 9 Dec 2010 18:07:52 +0900 Subject: ASoC: WM8580: Fix R8 initial value commit a0968628097380be52db8b4664da98fc425546a5 upstream. Acc to WM8580 manual, the default value for R8 is 0x10, not 0x1c. Signed-off-by: Seungwhan Youn Acked-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/soc/codecs/wm8580.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 72deeabef4fe..a961fc6f0c5f 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -171,7 +171,7 @@ static const u16 wm8580_reg[] = { 0x0121, 0x017e, 0x007d, 0x0014, /*R3*/ 0x0121, 0x017e, 0x007d, 0x0194, /*R7*/ - 0x001c, 0x0002, 0x0002, 0x00c2, /*R11*/ + 0x0010, 0x0002, 0x0002, 0x00c2, /*R11*/ 0x0182, 0x0082, 0x000a, 0x0024, /*R15*/ 0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/ 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/ -- cgit v1.2.3 From 6d597031f300ad36db98f888bb148914a2b0386b Mon Sep 17 00:00:00 2001 From: Dmitry Artamonow Date: Wed, 8 Dec 2010 23:36:17 +0300 Subject: ASoC: fix deemphasis control in wm8904/55/60 codecs commit 3f343f8512c7882a3637d9aea4ec6b3801cbcdc5 upstream. Deemphasis control's .get callback should update control's value instead of returning it - return value of callback function is used for indicating error or success of operation. Signed-off-by: Dmitry Artamonow Acked-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/soc/codecs/wm8904.c | 3 ++- sound/soc/codecs/wm8955.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 87f14f8675fa..e21b80aaf418 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -820,7 +820,8 @@ static int wm8904_get_deemph(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - return wm8904->deemph; + ucontrol->value.enumerated.item[0] = wm8904->deemph; + return 0; } static int wm8904_put_deemph(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index fedb76452f1b..12d04d7b0fff 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -384,7 +384,8 @@ static int wm8955_get_deemph(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); - return wm8955->deemph; + ucontrol->value.enumerated.item[0] = wm8955->deemph; + return 0; } static int wm8955_put_deemph(struct snd_kcontrol *kcontrol, -- cgit v1.2.3 From 8724a1ca50969118196309121f0ba7179bcf8ee1 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 16 Nov 2010 13:23:50 -0800 Subject: bootmem: Add alloc_bootmem_align() commit 53dde5f385bc56e312f78b7cb25ffaf8efd4735d upstream. Add an alloc_bootmem_align() interface to allocate bootmem with specified alignment. This is necessary to be able to allocate the xsave area in a subsequent patch. Signed-off-by: Suresh Siddha Signed-off-by: Andi Kleen LKML-Reference: <20101116212441.977574826@sbsiddha-MOBL3.sc.intel.com> Acked-by: H. Peter Anvin Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- include/linux/bootmem.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index 266ab9291232..499dfe982a0e 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h @@ -105,6 +105,8 @@ extern void *__alloc_bootmem_low_node(pg_data_t *pgdat, #define alloc_bootmem(x) \ __alloc_bootmem(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) +#define alloc_bootmem_align(x, align) \ + __alloc_bootmem(x, align, __pa(MAX_DMA_ADDRESS)) #define alloc_bootmem_nopanic(x) \ __alloc_bootmem_nopanic(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) #define alloc_bootmem_pages(x) \ -- cgit v1.2.3 From cc5d8c885a5ee338ab69f39e59f6703bdb901496 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 16 Nov 2010 13:23:51 -0800 Subject: x86, xsave: Use alloc_bootmem_align() instead of alloc_bootmem() commit 10340ae130fb70352eae1ae8a00b7906d91bf166 upstream. Alignment of alloc_bootmem() depends on the value of L1_CACHE_SHIFT. What we need here, however, is 64 byte alignment. Use alloc_bootmem_align() and explicitly specify the alignment instead. This fixes a kernel boot crash reported by Jody when the cpu in .config is set to MPENTIUMII but the kernel is booted on a xsave-capable CPU. Reported-by: Jody Bruchon Signed-off-by: Suresh Siddha Signed-off-by: Andi Kleen LKML-Reference: <20101116212442.059967454@sbsiddha-MOBL3.sc.intel.com> Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/xsave.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 37e68fc5e24a..aa8bf4fcf725 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -305,7 +305,8 @@ void __cpuinit xsave_init(void) */ static void __init setup_xstate_init(void) { - init_xstate_buf = alloc_bootmem(xstate_size); + init_xstate_buf = alloc_bootmem_align(xstate_size, + __alignof__(struct xsave_struct)); init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT; } -- cgit v1.2.3 From 83ec6d3cccb0cd67613880b32c85fec88233d681 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 13 Oct 2010 09:13:12 +0000 Subject: IB/uverbs: Handle large number of entries in poll CQ commit 7182afea8d1afd432a17c18162cc3fd441d0da93 upstream. In ib_uverbs_poll_cq() code there is a potential integer overflow if userspace passes in a large cmd.ne. The calls to kmalloc() would allocate smaller buffers than intended, leading to memory corruption. There iss also an information leak if resp wasn't all used. Unprivileged userspace may call this function, although only if an RDMA device that uses this function is present. Fix this by copying CQ entries one at a time, which avoids the allocation entirely, and also by moving this copying into a function that makes sure to initialize all memory copied to userspace. Special thanks to Jason Gunthorpe for his help and advice. Signed-off-by: Dan Carpenter Signed-off-by: Andi Kleen [ Monkey around with things a bit to avoid bad code generation by gcc when designated initializers are used. - Roland ] Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/core/uverbs_cmd.c | 99 ++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 43 deletions(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 6fcfbeb24a23..abb87140f29f 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -891,68 +891,81 @@ out: return ret ? ret : in_len; } +static int copy_wc_to_user(void __user *dest, struct ib_wc *wc) +{ + struct ib_uverbs_wc tmp; + + tmp.wr_id = wc->wr_id; + tmp.status = wc->status; + tmp.opcode = wc->opcode; + tmp.vendor_err = wc->vendor_err; + tmp.byte_len = wc->byte_len; + tmp.ex.imm_data = (__u32 __force) wc->ex.imm_data; + tmp.qp_num = wc->qp->qp_num; + tmp.src_qp = wc->src_qp; + tmp.wc_flags = wc->wc_flags; + tmp.pkey_index = wc->pkey_index; + tmp.slid = wc->slid; + tmp.sl = wc->sl; + tmp.dlid_path_bits = wc->dlid_path_bits; + tmp.port_num = wc->port_num; + tmp.reserved = 0; + + if (copy_to_user(dest, &tmp, sizeof tmp)) + return -EFAULT; + + return 0; +} + ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len) { struct ib_uverbs_poll_cq cmd; - struct ib_uverbs_poll_cq_resp *resp; + struct ib_uverbs_poll_cq_resp resp; + u8 __user *header_ptr; + u8 __user *data_ptr; struct ib_cq *cq; - struct ib_wc *wc; - int ret = 0; - int i; - int rsize; + struct ib_wc wc; + int ret; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - wc = kmalloc(cmd.ne * sizeof *wc, GFP_KERNEL); - if (!wc) - return -ENOMEM; - - rsize = sizeof *resp + cmd.ne * sizeof(struct ib_uverbs_wc); - resp = kmalloc(rsize, GFP_KERNEL); - if (!resp) { - ret = -ENOMEM; - goto out_wc; - } - cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0); - if (!cq) { - ret = -EINVAL; - goto out; - } + if (!cq) + return -EINVAL; - resp->count = ib_poll_cq(cq, cmd.ne, wc); + /* we copy a struct ib_uverbs_poll_cq_resp to user space */ + header_ptr = (void __user *)(unsigned long) cmd.response; + data_ptr = header_ptr + sizeof resp; - put_cq_read(cq); + memset(&resp, 0, sizeof resp); + while (resp.count < cmd.ne) { + ret = ib_poll_cq(cq, 1, &wc); + if (ret < 0) + goto out_put; + if (!ret) + break; + + ret = copy_wc_to_user(data_ptr, &wc); + if (ret) + goto out_put; - for (i = 0; i < resp->count; i++) { - resp->wc[i].wr_id = wc[i].wr_id; - resp->wc[i].status = wc[i].status; - resp->wc[i].opcode = wc[i].opcode; - resp->wc[i].vendor_err = wc[i].vendor_err; - resp->wc[i].byte_len = wc[i].byte_len; - resp->wc[i].ex.imm_data = (__u32 __force) wc[i].ex.imm_data; - resp->wc[i].qp_num = wc[i].qp->qp_num; - resp->wc[i].src_qp = wc[i].src_qp; - resp->wc[i].wc_flags = wc[i].wc_flags; - resp->wc[i].pkey_index = wc[i].pkey_index; - resp->wc[i].slid = wc[i].slid; - resp->wc[i].sl = wc[i].sl; - resp->wc[i].dlid_path_bits = wc[i].dlid_path_bits; - resp->wc[i].port_num = wc[i].port_num; + data_ptr += sizeof(struct ib_uverbs_wc); + ++resp.count; } - if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize)) + if (copy_to_user(header_ptr, &resp, sizeof resp)) { ret = -EFAULT; + goto out_put; + } -out: - kfree(resp); + ret = in_len; -out_wc: - kfree(wc); - return ret ? ret : in_len; +out_put: + put_cq_read(cq); + return ret; } ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file, -- cgit v1.2.3 From c85b1ca3a94d0a1de278faf545daa765f671b59b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 10 Dec 2010 00:16:39 +0100 Subject: PM / Hibernate: Fix PM_POST_* notification with user-space suspend commit 1497dd1d29c6a53fcd3c80f7ac8d0e0239e7389e upstream. The user-space hibernation sends a wrong notification after the image restoration because of thinko for the file flag check. RDONLY corresponds to hibernation and WRONLY to restoration, confusingly. Signed-off-by: Takashi Iwai Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/power/user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/power/user.c b/kernel/power/user.c index 1b2ea31e6bd8..c36c3b9e8a84 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -137,7 +137,7 @@ static int snapshot_release(struct inode *inode, struct file *filp) free_all_swap_pages(data->swap); if (data->frozen) thaw_processes(); - pm_notifier_call_chain(data->mode == O_WRONLY ? + pm_notifier_call_chain(data->mode == O_RDONLY ? PM_POST_HIBERNATION : PM_POST_RESTORE); atomic_inc(&snapshot_device_available); -- cgit v1.2.3 From b0bb779b06b9b41e6e40d70300a99ca72a1b1873 Mon Sep 17 00:00:00 2001 From: Valentine Barshak Date: Tue, 14 Dec 2010 00:03:16 +0100 Subject: ARM: 6535/1: V6 MPCore v6_dma_inv_range and v6_dma_flush_range RWFO fix commit 85b093bcc5322baa811a03ec73de0909c157f181 upstream. Cache ownership must be acquired by reading/writing data from the cache line to make cache operation have the desired effect on the SMP MPCore CPU. However, the ownership is never acquired in the v6_dma_inv_range function when cleaning the first line and flushing the last one, in case the address is not aligned to D_CACHE_LINE_SIZE boundary. Fix this by reading/writing data if needed, before performing cache operations. While at it, fix v6_dma_flush_range to prevent RWFO outside the buffer. Signed-off-by: Valentine Barshak Signed-off-by: George G. Davis Acked-by: Catalin Marinas Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/arm/mm/cache-v6.S | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 86aa689ef1aa..47010d8114b0 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S @@ -196,6 +196,10 @@ ENTRY(v6_flush_kern_dcache_area) * - end - virtual end address of region */ v6_dma_inv_range: +#ifdef CONFIG_DMA_CACHE_RWFO + ldrb r2, [r0] @ read for ownership + strb r2, [r0] @ write for ownership +#endif tst r0, #D_CACHE_LINE_SIZE - 1 bic r0, r0, #D_CACHE_LINE_SIZE - 1 #ifdef HARVARD_CACHE @@ -204,6 +208,10 @@ v6_dma_inv_range: mcrne p15, 0, r0, c7, c11, 1 @ clean unified line #endif tst r1, #D_CACHE_LINE_SIZE - 1 +#ifdef CONFIG_DMA_CACHE_RWFO + ldrneb r2, [r1, #-1] @ read for ownership + strneb r2, [r1, #-1] @ write for ownership +#endif bic r1, r1, #D_CACHE_LINE_SIZE - 1 #ifdef HARVARD_CACHE mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D line @@ -211,10 +219,6 @@ v6_dma_inv_range: mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line #endif 1: -#ifdef CONFIG_DMA_CACHE_RWFO - ldr r2, [r0] @ read for ownership - str r2, [r0] @ write for ownership -#endif #ifdef HARVARD_CACHE mcr p15, 0, r0, c7, c6, 1 @ invalidate D line #else @@ -222,6 +226,10 @@ v6_dma_inv_range: #endif add r0, r0, #D_CACHE_LINE_SIZE cmp r0, r1 +#ifdef CONFIG_DMA_CACHE_RWFO + ldrlo r2, [r0] @ read for ownership + strlo r2, [r0] @ write for ownership +#endif blo 1b mov r0, #0 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer @@ -256,12 +264,12 @@ v6_dma_clean_range: * - end - virtual end address of region */ ENTRY(v6_dma_flush_range) - bic r0, r0, #D_CACHE_LINE_SIZE - 1 -1: #ifdef CONFIG_DMA_CACHE_RWFO - ldr r2, [r0] @ read for ownership - str r2, [r0] @ write for ownership + ldrb r2, [r0] @ read for ownership + strb r2, [r0] @ write for ownership #endif + bic r0, r0, #D_CACHE_LINE_SIZE - 1 +1: #ifdef HARVARD_CACHE mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line #else @@ -269,6 +277,10 @@ ENTRY(v6_dma_flush_range) #endif add r0, r0, #D_CACHE_LINE_SIZE cmp r0, r1 +#ifdef CONFIG_DMA_CACHE_RWFO + ldrlob r2, [r0] @ read for ownership + strlob r2, [r0] @ write for ownership +#endif blo 1b mov r0, #0 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer -- cgit v1.2.3 From e54e2bc342ab4be42927a81ced977ab4b83b1ee8 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Tue, 23 Nov 2010 16:52:48 -0800 Subject: qla2xxx: Correct issue where NPIV-config data was not being allocated for 82xx parts. commit 087c621e22f49c326cdc65d98c6fc0737ac13533 upstream. This would cause a panic while reading the NPIV-config data. Signed-off-by: Andrew Vasquez Signed-off-by: Madhuranath Iyengar Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/scsi/qla2xxx/qla_os.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index be1a8fcbb1fb..8dc5fb1031dd 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2102,6 +2102,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->init_cb_size = sizeof(struct mid_init_cb_81xx); ha->gid_list_info_size = 8; ha->optrom_size = OPTROM_SIZE_82XX; + ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX; ha->isp_ops = &qla82xx_isp_ops; ha->flash_conf_off = FARX_ACCESS_FLASH_CONF; ha->flash_data_off = FARX_ACCESS_FLASH_DATA; -- cgit v1.2.3 From 80cb488d71fe19df2f0883ab13bc7d1bd9d48b00 Mon Sep 17 00:00:00 2001 From: Mike Hernandez Date: Tue, 23 Nov 2010 16:52:46 -0800 Subject: qla2xxx: Populate Command Type 6 LUN field properly. commit 85727e1f78bd8392a0657ad6a4ff85fef1cc4a6d upstream. Use the host_to_fcp_swap call to correctly populate the LUN field in the Command Type 6 path. This field is used during LUN reset cleanup and must match the field used in the FCP command. Signed-off-by: Mike Hernandez Signed-off-by: Madhuranath Iyengar Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/scsi/qla2xxx/qla_iocb.c | 1 + drivers/scsi/qla2xxx/qla_nx.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 8ef945365412..1fcb89e42906 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -1122,6 +1122,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, fcp_cmnd->additional_cdb_len |= 2; int_to_scsilun(sp->cmd->device->lun, &fcp_cmnd->lun); + host_to_fcp_swap((uint8_t *)&fcp_cmnd->lun, sizeof(fcp_cmnd->lun)); memcpy(fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len); cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(fcp_cmnd_len); cmd_pkt->fcp_cmnd_dseg_address[0] = cpu_to_le32( diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index ff562de0e8e7..e9d933387bf7 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -2798,6 +2798,7 @@ sufficient_dsds: goto queuing_error_fcp_cmnd; int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun); + host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun)); /* build FCP_CMND IU */ memset(ctx->fcp_cmnd, 0, sizeof(struct fcp_cmnd)); -- cgit v1.2.3 From 687a93bcec28a4fca0f8db0ea756cd0c25361a84 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 5 Dec 2010 02:03:26 +0000 Subject: llc: fix a device refcount imbalance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 35d9b0c906ad92d32a0b8db5daa6fabfcc2f068d upstream. Le dimanche 05 décembre 2010 à 12:23 +0100, Eric Dumazet a écrit : > Le dimanche 05 décembre 2010 à 09:19 +0100, Eric Dumazet a écrit : > > > Hmm.. > > > > If somebody can explain why RTNL is held in arp_ioctl() (and therefore > > in arp_req_delete()), we might first remove RTNL use in arp_ioctl() so > > that your patch can be applied. > > > > Right now it is not good, because RTNL wont be necessarly held when you > > are going to call arp_invalidate() ? > > While doing this analysis, I found a refcount bug in llc, I'll send a > patch for net-2.6 Oh well, of course I must first fix the bug in net-2.6, and wait David pull the fix in net-next-2.6 before sending this rcu conversion. Note: this patch should be sent to stable teams (2.6.34 and up) [PATCH net-2.6] llc: fix a device refcount imbalance commit abf9d537fea225 (llc: add support for SO_BINDTODEVICE) added one refcount imbalance in llc_ui_bind(), because dev_getbyhwaddr() doesnt take a reference on device, while dev_get_by_index() does. Fix this using RCU locking. And since an RCU conversion will be done for 2.6.38 for dev_getbyhwaddr(), put the rcu_read_lock/unlock exactly at their final place. Signed-off-by: Eric Dumazet Signed-off-by: Andi Kleen Cc: Octavian Purdila Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/llc/af_llc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 582612998211..e35dbe55f520 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -317,8 +317,9 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) goto out; rc = -ENODEV; rtnl_lock(); + rcu_read_lock(); if (sk->sk_bound_dev_if) { - llc->dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if); + llc->dev = dev_get_by_index_rcu(&init_net, sk->sk_bound_dev_if); if (llc->dev) { if (!addr->sllc_arphrd) addr->sllc_arphrd = llc->dev->type; @@ -329,13 +330,13 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) !llc_mac_match(addr->sllc_mac, llc->dev->dev_addr)) { rc = -EINVAL; - dev_put(llc->dev); llc->dev = NULL; } } } else llc->dev = dev_getbyhwaddr(&init_net, addr->sllc_arphrd, addr->sllc_mac); + rcu_read_unlock(); rtnl_unlock(); if (!llc->dev) goto out; -- cgit v1.2.3 From 33afb8f469d30dc23985054ebe6a571bf33994b5 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 26 Nov 2010 23:24:31 +0530 Subject: ath9k: Disable SWBA interrupt on remove_interface commit 46047784b8cdcfc916f6c1cccee0c18dd1223dfd upstream. while removing beaconing mode interface, SWBA interrupt was never disabled when there are no other beaconing interfaces. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/ath/ath9k/main.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 1e2a68ea9355..82cfe0f28be6 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1501,6 +1501,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, struct ath_softc *sc = aphy->sc; struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_vif *avp = (void *)vif->drv_priv; + bool bs_valid = false; int i; ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); @@ -1529,7 +1530,15 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, "slot\n", __func__); sc->beacon.bslot[i] = NULL; sc->beacon.bslot_aphy[i] = NULL; - } + } else if (sc->beacon.bslot[i]) + bs_valid = true; + } + if (!bs_valid && (sc->sc_ah->imask & ATH9K_INT_SWBA)) { + /* Disable SWBA interrupt */ + sc->sc_ah->imask &= ~ATH9K_INT_SWBA; + ath9k_ps_wakeup(sc); + ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask); + ath9k_ps_restore(sc); } sc->nvifs--; -- cgit v1.2.3 From 798a5d41ed663468e5e02b1ebf028d6b06ed68bf Mon Sep 17 00:00:00 2001 From: Matteo Croce Date: Fri, 3 Dec 2010 02:25:08 +0100 Subject: ath9k: fix bug in tx power commit 841051602e3fa18ea468fe5a177aa92b6eb44b56 upstream. The ath9k driver subtracts 3 dBm to the txpower as with two radios the signal power is doubled. The resulting value is assigned in an u16 which overflows and makes the card work at full power. Signed-off-by: Matteo Croce Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/ath/ath9k/eeprom_def.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 54ce34ef1873..8f57ebf9e292 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -1064,15 +1064,19 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, case 1: break; case 2: - scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; + if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN) + scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; + else + scaledPower = 0; break; case 3: - scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; + if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN) + scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; + else + scaledPower = 0; break; } - scaledPower = max((u16)0, scaledPower); - if (IS_CHAN_2GHZ(chan)) { numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; -- cgit v1.2.3 From 3d0e4a52260a47ea1cac84b3ca16bb2582157b52 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Thu, 2 Dec 2010 18:44:09 +0100 Subject: mac80211: Fix BUG in pskb_expand_head when transmitting shared skbs commit 7e2447075690860e2cea96b119fc9cadbaa7e83c upstream. mac80211 doesn't handle shared skbs correctly at the moment. As a result a possible resize can trigger a BUG in pskb_expand_head. [ 676.030000] Kernel bug detected[#1]: [ 676.030000] Cpu 0 [ 676.030000] $ 0 : 00000000 00000000 819662ff 00000002 [ 676.030000] $ 4 : 81966200 00000020 00000000 00000020 [ 676.030000] $ 8 : 819662e0 800043c0 00000002 00020000 [ 676.030000] $12 : 3b9aca00 00000000 00000000 00470000 [ 676.030000] $16 : 80ea2000 00000000 00000000 00000000 [ 676.030000] $20 : 818aa200 80ea2018 80ea2000 00000008 [ 676.030000] $24 : 00000002 800ace5c [ 676.030000] $28 : 8199a000 8199bd20 81938f88 80f180d4 [ 676.030000] Hi : 0000026e [ 676.030000] Lo : 0000757e [ 676.030000] epc : 801245e4 pskb_expand_head+0x44/0x1d8 [ 676.030000] Not tainted [ 676.030000] ra : 80f180d4 ieee80211_skb_resize+0xb0/0x114 [mac80211] [ 676.030000] Status: 1000a403 KERNEL EXL IE [ 676.030000] Cause : 10800024 [ 676.030000] PrId : 0001964c (MIPS 24Kc) [ 676.030000] Modules linked in: mac80211_hwsim rt2800lib rt2x00soc rt2x00pci rt2x00lib mac80211 crc_itu_t crc_ccitt cfg80211 compat arc4 aes_generic deflate ecb cbc [last unloaded: rt2800pci] [ 676.030000] Process kpktgend_0 (pid: 97, threadinfo=8199a000, task=81879f48, tls=00000000) [ 676.030000] Stack : ffffffff 00000000 00000000 00000014 00000004 80ea2000 00000000 00000000 [ 676.030000] 818aa200 80f180d4 ffffffff 0000000a 81879f78 81879f48 81879f48 00000018 [ 676.030000] 81966246 80ea2000 818432e0 80f1a420 80203050 81814d98 00000001 81879f48 [ 676.030000] 81879f48 00000018 81966246 818432e0 0000001a 8199bdd4 0000001c 80f1b72c [ 676.030000] 80203020 8001292c 80ef4aa2 7f10b55d 801ab5b8 81879f48 00000188 80005c90 [ 676.030000] ... [ 676.030000] Call Trace: [ 676.030000] [<801245e4>] pskb_expand_head+0x44/0x1d8 [ 676.030000] [<80f180d4>] ieee80211_skb_resize+0xb0/0x114 [mac80211] [ 676.030000] [<80f1a420>] ieee80211_xmit+0x150/0x22c [mac80211] [ 676.030000] [<80f1b72c>] ieee80211_subif_start_xmit+0x6f4/0x73c [mac80211] [ 676.030000] [<8014361c>] pktgen_thread_worker+0xfac/0x16f8 [ 676.030000] [<8002ebe8>] kthread+0x7c/0x88 [ 676.030000] [<80008e0c>] kernel_thread_helper+0x10/0x18 [ 676.030000] [ 676.030000] [ 676.030000] Code: 24020001 10620005 2502001f <0200000d> 0804917a 00000000 2502001f 00441023 00531021 Fix this by making a local copy of shared skbs prior to mangeling them. To avoid copying the skb unnecessarily move the skb_copy call below the checks that don't need write access to the skb. Also, move the assignment of nh_pos and h_pos below the skb_copy to point to the correct skb. It would be possible to avoid another resize of the copied skb by using skb_copy_expand instead of skb_copy but that would make the patch more complex. Also, shared skbs are a corner case right now, so the resize shouldn't matter much. Cc: Johannes Berg Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/mac80211/tx.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 680bcb7093db..10910d62d8cd 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1679,15 +1679,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, int nh_pos, h_pos; struct sta_info *sta = NULL; u32 sta_flags = 0; + struct sk_buff *tmp_skb; if (unlikely(skb->len < ETH_HLEN)) { ret = NETDEV_TX_OK; goto fail; } - nh_pos = skb_network_header(skb) - skb->data; - h_pos = skb_transport_header(skb) - skb->data; - /* convert Ethernet header to proper 802.11 header (based on * operation mode) */ ethertype = (skb->data[12] << 8) | skb->data[13]; @@ -1859,6 +1857,20 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, goto fail; } + /* + * If the skb is shared we need to obtain our own copy. + */ + if (skb_shared(skb)) { + tmp_skb = skb; + skb = skb_copy(skb, GFP_ATOMIC); + kfree_skb(tmp_skb); + + if (!skb) { + ret = NETDEV_TX_OK; + goto fail; + } + } + hdr.frame_control = fc; hdr.duration_id = 0; hdr.seq_ctrl = 0; @@ -1877,6 +1889,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, encaps_len = 0; } + nh_pos = skb_network_header(skb) - skb->data; + h_pos = skb_transport_header(skb) - skb->data; + skb_pull(skb, skip_header_bytes); nh_pos -= skip_header_bytes; h_pos -= skip_header_bytes; -- cgit v1.2.3 From aeb51d41f63a8e836a055b56d9b59ec895eac312 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 29 Oct 2010 13:25:24 -0700 Subject: SPARC/LEON: removed constant timer initialization as if HZ=100, now it reflects the value of HZ [ Upstream commit b690c425fe07c725e7f1f7d40303588416cba67f ] Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/sparc/kernel/leon_kernel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 6a7b4dbc8e09..dcefd2211552 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -114,7 +114,7 @@ void __init leon_init_timers(irq_handler_t counter_fn) if (leon3_gptimer_regs && leon3_irqctrl_regs) { LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0); LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld, - (((1000000 / 100) - 1))); + (((1000000 / HZ) - 1))); LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0); #ifdef CONFIG_SMP @@ -128,7 +128,7 @@ void __init leon_init_timers(irq_handler_t counter_fn) } LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].val, 0); - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/100) - 1))); + LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/HZ) - 1))); LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0); # endif -- cgit v1.2.3 From 55e056f742d2032972062a832316a822f7e801b6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 16 Nov 2010 12:08:23 -0800 Subject: sparc64: Delete prom_puts() unused. [ Upstream commit ce05a94efaf71d562eeefd30d6bbc2ab42b06bac ] Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/sparc/prom/console_64.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/arch/sparc/prom/console_64.c b/arch/sparc/prom/console_64.c index 10322dc2f557..de67fc73d91e 100644 --- a/arch/sparc/prom/console_64.c +++ b/arch/sparc/prom/console_64.c @@ -81,19 +81,3 @@ prom_putchar(char c) { prom_nbputchar(c); } - -void -prom_puts(const char *s, int len) -{ - unsigned long args[7]; - - args[0] = (unsigned long) "write"; - args[1] = 3; - args[2] = 1; - args[3] = (unsigned int) prom_stdout; - args[4] = (unsigned long) s; - args[5] = len; - args[6] = (unsigned long) -1; - - p1275_cmd_direct(args); -} -- cgit v1.2.3 From e63907b82666ff267e816e2b781f3c14b7d02d95 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 16 Nov 2010 12:11:15 -0800 Subject: sparc: Remove prom_pathtoinode() [ Upstream commit 17d70d6df0c4ea7a203b444001572a91ad9c2bef ] Unused. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/sparc/include/asm/oplib_32.h | 1 - arch/sparc/include/asm/oplib_64.h | 1 - arch/sparc/prom/tree_32.c | 15 --------------- arch/sparc/prom/tree_64.c | 18 ------------------ 4 files changed, 35 deletions(-) diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h index 33e31ce6b31f..72bc43c42cc2 100644 --- a/arch/sparc/include/asm/oplib_32.h +++ b/arch/sparc/include/asm/oplib_32.h @@ -238,7 +238,6 @@ extern int prom_node_has_property(int node, char *property); extern int prom_setprop(int node, const char *prop_name, char *prop_value, int value_size); -extern int prom_pathtoinode(char *path); extern int prom_inst2pkg(int); /* Dorking with Bus ranges... */ diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h index 3e0b2d62303d..061c6a3c7cac 100644 --- a/arch/sparc/include/asm/oplib_64.h +++ b/arch/sparc/include/asm/oplib_64.h @@ -278,7 +278,6 @@ extern int prom_finddevice(const char *name); extern int prom_setprop(int node, const char *prop_name, char *prop_value, int value_size); -extern int prom_pathtoinode(const char *path); extern int prom_inst2pkg(int); extern int prom_service_exists(const char *service_name); extern void prom_sun4v_guest_soft_state(void); diff --git a/arch/sparc/prom/tree_32.c b/arch/sparc/prom/tree_32.c index b21592f8e3fe..71e7f080a576 100644 --- a/arch/sparc/prom/tree_32.c +++ b/arch/sparc/prom/tree_32.c @@ -341,18 +341,3 @@ int prom_inst2pkg(int inst) if (node == -1) return 0; return node; } - -/* Return 'node' assigned to a particular prom 'path' - * FIXME: Should work for v0 as well - */ -int prom_pathtoinode(char *path) -{ - int node, inst; - - inst = prom_devopen (path); - if (inst == -1) return 0; - node = prom_inst2pkg (inst); - prom_devclose (inst); - if (node == -1) return 0; - return node; -} diff --git a/arch/sparc/prom/tree_64.c b/arch/sparc/prom/tree_64.c index 9d3f9137a43a..8327b1b68f4b 100644 --- a/arch/sparc/prom/tree_64.c +++ b/arch/sparc/prom/tree_64.c @@ -374,24 +374,6 @@ inline int prom_inst2pkg(int inst) return node; } -/* Return 'node' assigned to a particular prom 'path' - * FIXME: Should work for v0 as well - */ -int -prom_pathtoinode(const char *path) -{ - int node, inst; - - inst = prom_devopen (path); - if (inst == 0) - return 0; - node = prom_inst2pkg(inst); - prom_devclose(inst); - if (node == -1) - return 0; - return node; -} - int prom_ihandle2path(int handle, char *buffer, int bufsize) { unsigned long args[7]; -- cgit v1.2.3 From 785bdcaa9babda16ce7c081966dd3d316a253b0b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 16 Nov 2010 12:23:20 -0800 Subject: sparc: Kill prom devops_{32,64}.c [ Upstream commit b148246912bea92bde2a0cba125ca94f1f776b12 ] Completely unused. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/sparc/include/asm/oplib_32.h | 19 --------- arch/sparc/include/asm/oplib_64.h | 21 ---------- arch/sparc/prom/Makefile | 1 - arch/sparc/prom/devops_32.c | 87 --------------------------------------- arch/sparc/prom/devops_64.c | 67 ------------------------------ 5 files changed, 195 deletions(-) delete mode 100644 arch/sparc/prom/devops_32.c delete mode 100644 arch/sparc/prom/devops_64.c diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h index 72bc43c42cc2..66df2b15c883 100644 --- a/arch/sparc/include/asm/oplib_32.h +++ b/arch/sparc/include/asm/oplib_32.h @@ -60,25 +60,6 @@ extern char *prom_getbootargs(void); extern char *prom_mapio(char *virt_hint, int io_space, unsigned int phys_addr, unsigned int num_bytes); extern void prom_unmapio(char *virt_addr, unsigned int num_bytes); -/* Device operations. */ - -/* Open the device described by the passed string. Note, that the format - * of the string is different on V0 vs. V2->higher proms. The caller must - * know what he/she is doing! Returns the device descriptor, an int. - */ -extern int prom_devopen(char *device_string); - -/* Close a previously opened device described by the passed integer - * descriptor. - */ -extern int prom_devclose(int device_handle); - -/* Do a seek operation on the device described by the passed integer - * descriptor. - */ -extern void prom_seek(int device_handle, unsigned int seek_hival, - unsigned int seek_lowval); - /* Miscellaneous routines, don't really fit in any category per se. */ /* Reboot the machine with the command line passed. */ diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h index 061c6a3c7cac..e7a53a3cfd6b 100644 --- a/arch/sparc/include/asm/oplib_64.h +++ b/arch/sparc/include/asm/oplib_64.h @@ -67,27 +67,6 @@ extern void prom_init(void *cif_handler, void *cif_stack); /* Boot argument acquisition, returns the boot command line string. */ extern char *prom_getbootargs(void); -/* Device utilities. */ - -/* Device operations. */ - -/* Open the device described by the passed string. Note, that the format - * of the string is different on V0 vs. V2->higher proms. The caller must - * know what he/she is doing! Returns the device descriptor, an int. - */ -extern int prom_devopen(const char *device_string); - -/* Close a previously opened device described by the passed integer - * descriptor. - */ -extern int prom_devclose(int device_handle); - -/* Do a seek operation on the device described by the passed integer - * descriptor. - */ -extern void prom_seek(int device_handle, unsigned int seek_hival, - unsigned int seek_lowval); - /* Miscellaneous routines, don't really fit in any category per se. */ /* Reboot the machine with the command line passed. */ diff --git a/arch/sparc/prom/Makefile b/arch/sparc/prom/Makefile index 1b8c073adb44..816c0fa12dc0 100644 --- a/arch/sparc/prom/Makefile +++ b/arch/sparc/prom/Makefile @@ -6,7 +6,6 @@ ccflags := -Werror lib-y := bootstr_$(BITS).o lib-$(CONFIG_SPARC32) += devmap.o -lib-y += devops_$(BITS).o lib-y += init_$(BITS).o lib-$(CONFIG_SPARC32) += memory.o lib-y += misc_$(BITS).o diff --git a/arch/sparc/prom/devops_32.c b/arch/sparc/prom/devops_32.c deleted file mode 100644 index 9c5d4687242a..000000000000 --- a/arch/sparc/prom/devops_32.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * devops.c: Device operations using the PROM. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - */ -#include -#include -#include - -#include -#include - -extern void restore_current(void); - -/* Open the device described by the string 'dstr'. Returns the handle - * to that device used for subsequent operations on that device. - * Returns -1 on failure. - */ -int -prom_devopen(char *dstr) -{ - int handle; - unsigned long flags; - spin_lock_irqsave(&prom_lock, flags); - switch(prom_vers) { - case PROM_V0: - handle = (*(romvec->pv_v0devops.v0_devopen))(dstr); - if(handle == 0) handle = -1; - break; - case PROM_V2: - case PROM_V3: - handle = (*(romvec->pv_v2devops.v2_dev_open))(dstr); - break; - default: - handle = -1; - break; - }; - restore_current(); - spin_unlock_irqrestore(&prom_lock, flags); - - return handle; -} - -/* Close the device described by device handle 'dhandle'. */ -int -prom_devclose(int dhandle) -{ - unsigned long flags; - spin_lock_irqsave(&prom_lock, flags); - switch(prom_vers) { - case PROM_V0: - (*(romvec->pv_v0devops.v0_devclose))(dhandle); - break; - case PROM_V2: - case PROM_V3: - (*(romvec->pv_v2devops.v2_dev_close))(dhandle); - break; - default: - break; - }; - restore_current(); - spin_unlock_irqrestore(&prom_lock, flags); - return 0; -} - -/* Seek to specified location described by 'seekhi' and 'seeklo' - * for device 'dhandle'. - */ -void -prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo) -{ - unsigned long flags; - spin_lock_irqsave(&prom_lock, flags); - switch(prom_vers) { - case PROM_V0: - (*(romvec->pv_v0devops.v0_seekdev))(dhandle, seekhi, seeklo); - break; - case PROM_V2: - case PROM_V3: - (*(romvec->pv_v2devops.v2_dev_seek))(dhandle, seekhi, seeklo); - break; - default: - break; - }; - restore_current(); - spin_unlock_irqrestore(&prom_lock, flags); -} diff --git a/arch/sparc/prom/devops_64.c b/arch/sparc/prom/devops_64.c deleted file mode 100644 index a017119e7ef1..000000000000 --- a/arch/sparc/prom/devops_64.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * devops.c: Device operations using the PROM. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ -#include -#include -#include - -#include -#include - -/* Open the device described by the string 'dstr'. Returns the handle - * to that device used for subsequent operations on that device. - * Returns 0 on failure. - */ -int -prom_devopen(const char *dstr) -{ - unsigned long args[5]; - - args[0] = (unsigned long) "open"; - args[1] = 1; - args[2] = 1; - args[3] = (unsigned long) dstr; - args[4] = (unsigned long) -1; - - p1275_cmd_direct(args); - - return (int) args[4]; -} - -/* Close the device described by device handle 'dhandle'. */ -int -prom_devclose(int dhandle) -{ - unsigned long args[4]; - - args[0] = (unsigned long) "close"; - args[1] = 1; - args[2] = 0; - args[3] = (unsigned int) dhandle; - - p1275_cmd_direct(args); - - return 0; -} - -/* Seek to specified location described by 'seekhi' and 'seeklo' - * for device 'dhandle'. - */ -void -prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo) -{ - unsigned long args[7]; - - args[0] = (unsigned long) "seek"; - args[1] = 3; - args[2] = 1; - args[3] = (unsigned int) dhandle; - args[4] = seekhi; - args[5] = seeklo; - args[6] = (unsigned long) -1; - - p1275_cmd_direct(args); -} -- cgit v1.2.3 From 4d05954829617507c44318015dc005b665ab564b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 16 Nov 2010 12:24:16 -0800 Subject: sparc64: Unexport prom_service_exists(). [ Upstream commit f7b5f55ac1623dfde24ef5319ad77c1746645f3f ] Only used by functions in misc_64.c so make it private to that file. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/sparc/include/asm/oplib_64.h | 1 - arch/sparc/prom/misc_64.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h index e7a53a3cfd6b..1c81a27fe0d0 100644 --- a/arch/sparc/include/asm/oplib_64.h +++ b/arch/sparc/include/asm/oplib_64.h @@ -258,7 +258,6 @@ extern int prom_setprop(int node, const char *prop_name, char *prop_value, int value_size); extern int prom_inst2pkg(int); -extern int prom_service_exists(const char *service_name); extern void prom_sun4v_guest_soft_state(void); extern int prom_ihandle2path(int handle, char *buffer, int bufsize); diff --git a/arch/sparc/prom/misc_64.c b/arch/sparc/prom/misc_64.c index 6cb1581d6aef..4a898935acba 100644 --- a/arch/sparc/prom/misc_64.c +++ b/arch/sparc/prom/misc_64.c @@ -18,7 +18,7 @@ #include #include -int prom_service_exists(const char *service_name) +static int prom_service_exists(const char *service_name) { unsigned long args[5]; -- cgit v1.2.3 From 91d6efa40733c84a21bfd2173f1187da2077c262 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 16 Nov 2010 12:50:19 -0800 Subject: sparc64: Delete prom_setcallback(). [ Upstream commit c540ee70e49b573535c7ddfd0e9a0fc9d549c8b7 ] Unused. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/sparc/include/asm/oplib_64.h | 8 -------- arch/sparc/prom/misc_64.c | 14 -------------- 2 files changed, 22 deletions(-) diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h index 1c81a27fe0d0..7ab973d0190d 100644 --- a/arch/sparc/include/asm/oplib_64.h +++ b/arch/sparc/include/asm/oplib_64.h @@ -88,14 +88,6 @@ extern void prom_halt(void) __attribute__ ((noreturn)); /* Halt and power-off the machine. */ extern void prom_halt_power_off(void) __attribute__ ((noreturn)); -/* Set the PROM 'sync' callback function to the passed function pointer. - * When the user gives the 'sync' command at the prom prompt while the - * kernel is still active, the prom will call this routine. - * - */ -typedef int (*callback_func_t)(long *cmd); -extern void prom_setcallback(callback_func_t func_ptr); - /* Acquire the IDPROM of the root node in the prom device tree. This * gets passed a buffer where you would like it stuffed. The return value * is the format type of this idprom or 0xff on error. diff --git a/arch/sparc/prom/misc_64.c b/arch/sparc/prom/misc_64.c index 4a898935acba..2fdcebf9a5df 100644 --- a/arch/sparc/prom/misc_64.c +++ b/arch/sparc/prom/misc_64.c @@ -150,20 +150,6 @@ void prom_halt_power_off(void) prom_halt(); } -/* Set prom sync handler to call function 'funcp'. */ -void prom_setcallback(callback_func_t funcp) -{ - unsigned long args[5]; - if (!funcp) - return; - args[0] = (unsigned long) "set-callback"; - args[1] = 1; - args[2] = 1; - args[3] = (unsigned long) funcp; - args[4] = (unsigned long) -1; - p1275_cmd_direct(args); -} - /* Get the idprom and stuff it into buffer 'idbuf'. Returns the * format type. 'num_bytes' is the number of bytes that your idbuf * has space for. Returns 0xff on error. -- cgit v1.2.3 From 2b06fa9327ca7ebc1f2001dbf7938732e6b07cce Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 17 Nov 2010 10:22:56 -0800 Subject: sparc: Do not export prom_nb{get,put}char(). [ Upstream commit 91921fef7c658b12de53376b312d071d757f7770 ] Never used outside of console_{32,64}.c Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/sparc/include/asm/oplib_32.h | 6 ------ arch/sparc/include/asm/oplib_64.h | 6 ------ arch/sparc/prom/console_32.c | 6 ++---- arch/sparc/prom/console_64.c | 6 ++---- 4 files changed, 4 insertions(+), 20 deletions(-) diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h index 66df2b15c883..ca51a666f623 100644 --- a/arch/sparc/include/asm/oplib_32.h +++ b/arch/sparc/include/asm/oplib_32.h @@ -104,12 +104,6 @@ extern int prom_getprev(void); /* Character operations to/from the console.... */ -/* Non-blocking get character from console. */ -extern int prom_nbgetchar(void); - -/* Non-blocking put character to console. */ -extern int prom_nbputchar(char character); - /* Blocking get character from console. */ extern char prom_getchar(void); diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h index 7ab973d0190d..0d614e3f0871 100644 --- a/arch/sparc/include/asm/oplib_64.h +++ b/arch/sparc/include/asm/oplib_64.h @@ -96,12 +96,6 @@ extern unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size); /* Character operations to/from the console.... */ -/* Non-blocking get character from console. */ -extern int prom_nbgetchar(void); - -/* Non-blocking put character to console. */ -extern int prom_nbputchar(char character); - /* Blocking get character from console. */ extern char prom_getchar(void); diff --git a/arch/sparc/prom/console_32.c b/arch/sparc/prom/console_32.c index 5340264b78f5..2ce5acb45f2d 100644 --- a/arch/sparc/prom/console_32.c +++ b/arch/sparc/prom/console_32.c @@ -19,8 +19,7 @@ extern void restore_current(void); /* Non blocking get character from console input device, returns -1 * if no input was taken. This can be used for polling. */ -int -prom_nbgetchar(void) +static int prom_nbgetchar(void) { static char inc; int i = -1; @@ -51,8 +50,7 @@ prom_nbgetchar(void) /* Non blocking put character to console device, returns -1 if * unsuccessful. */ -int -prom_nbputchar(char c) +static int prom_nbputchar(char c) { static char outc; unsigned long flags; diff --git a/arch/sparc/prom/console_64.c b/arch/sparc/prom/console_64.c index de67fc73d91e..33a8b275d6af 100644 --- a/arch/sparc/prom/console_64.c +++ b/arch/sparc/prom/console_64.c @@ -18,8 +18,7 @@ extern int prom_stdin, prom_stdout; /* Non blocking get character from console input device, returns -1 * if no input was taken. This can be used for polling. */ -inline int -prom_nbgetchar(void) +static int prom_nbgetchar(void) { unsigned long args[7]; char inc; @@ -42,8 +41,7 @@ prom_nbgetchar(void) /* Non blocking put character to console device, returns -1 if * unsuccessful. */ -inline int -prom_nbputchar(char c) +static int prom_nbputchar(char c) { unsigned long args[7]; char outc; -- cgit v1.2.3 From fc60be699493ebfb7f8b9559c680f82e800f4aae Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 30 Nov 2010 14:33:29 -0800 Subject: sparc: Pass buffer pointer all the way down to prom_{get,put}char(). [ Upstream commit e62cac1fd035b4cde707285008499dbe71955a86 ] This gets us closer to being able to eliminate the use of dynamic and stack based buffers, so that we can adhere to the "no buffer addresses above 4GB" rule for PROM calls. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/sparc/include/asm/openprom.h | 2 +- arch/sparc/include/asm/oplib_32.h | 4 ++-- arch/sparc/include/asm/oplib_64.h | 4 ++-- arch/sparc/prom/console_32.c | 50 +++++++++++++++++++-------------------- arch/sparc/prom/console_64.c | 34 +++++++++++++------------- arch/sparc/prom/printf.c | 15 ++++++------ 6 files changed, 55 insertions(+), 54 deletions(-) diff --git a/arch/sparc/include/asm/openprom.h b/arch/sparc/include/asm/openprom.h index 963e1a45c35f..f61a5017878f 100644 --- a/arch/sparc/include/asm/openprom.h +++ b/arch/sparc/include/asm/openprom.h @@ -37,7 +37,7 @@ struct linux_dev_v2_funcs { int (*v2_dev_open)(char *devpath); void (*v2_dev_close)(int d); int (*v2_dev_read)(int d, char *buf, int nbytes); - int (*v2_dev_write)(int d, char *buf, int nbytes); + int (*v2_dev_write)(int d, const char *buf, int nbytes); int (*v2_dev_seek)(int d, int hi, int lo); /* Never issued (multistage load support) */ diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h index ca51a666f623..4d708b7d5528 100644 --- a/arch/sparc/include/asm/oplib_32.h +++ b/arch/sparc/include/asm/oplib_32.h @@ -105,10 +105,10 @@ extern int prom_getprev(void); /* Character operations to/from the console.... */ /* Blocking get character from console. */ -extern char prom_getchar(void); +extern void prom_getchar(char *buf); /* Blocking put character to console. */ -extern void prom_putchar(char character); +extern void prom_putchar(const char *buf); /* Prom's internal routines, don't use in kernel/boot code. */ extern void prom_printf(const char *fmt, ...); diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h index 0d614e3f0871..891a00b655ee 100644 --- a/arch/sparc/include/asm/oplib_64.h +++ b/arch/sparc/include/asm/oplib_64.h @@ -97,10 +97,10 @@ extern unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size); /* Character operations to/from the console.... */ /* Blocking get character from console. */ -extern char prom_getchar(void); +extern void prom_getchar(char *buf); /* Blocking put character to console. */ -extern void prom_putchar(char character); +extern void prom_putchar(const char *buf); /* Prom's internal routines, don't use in kernel/boot code. */ extern void prom_printf(const char *fmt, ...); diff --git a/arch/sparc/prom/console_32.c b/arch/sparc/prom/console_32.c index 2ce5acb45f2d..69c16bbf1f48 100644 --- a/arch/sparc/prom/console_32.c +++ b/arch/sparc/prom/console_32.c @@ -19,27 +19,27 @@ extern void restore_current(void); /* Non blocking get character from console input device, returns -1 * if no input was taken. This can be used for polling. */ -static int prom_nbgetchar(void) +static int prom_nbgetchar(char *buf) { - static char inc; - int i = -1; unsigned long flags; + int i = -1; spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: i = (*(romvec->pv_nbgetchar))(); + if (i != -1) { + *buf = i; + i = 0; + } break; case PROM_V2: case PROM_V3: - if( (*(romvec->pv_v2devops).v2_dev_read)(*romvec->pv_v2bootargs.fd_stdin , &inc, 0x1) == 1) { - i = inc; - } else { - i = -1; - } + if ((*(romvec->pv_v2devops).v2_dev_read)(*romvec->pv_v2bootargs.fd_stdin, + buf, 0x1) == 1) + i = 0; break; default: - i = -1; break; }; restore_current(); @@ -50,27 +50,23 @@ static int prom_nbgetchar(void) /* Non blocking put character to console device, returns -1 if * unsuccessful. */ -static int prom_nbputchar(char c) +static int prom_nbputchar(const char *buf) { - static char outc; unsigned long flags; int i = -1; spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: - i = (*(romvec->pv_nbputchar))(c); + i = (*(romvec->pv_nbputchar))(*buf); break; case PROM_V2: case PROM_V3: - outc = c; - if( (*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout, &outc, 0x1) == 1) + if ((*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout, + buf, 0x1) == 1) i = 0; - else - i = -1; break; default: - i = -1; break; }; restore_current(); @@ -79,17 +75,21 @@ static int prom_nbputchar(char c) } /* Blocking version of get character routine above. */ -char -prom_getchar(void) +void prom_getchar(char *buf) { - int character; - while((character = prom_nbgetchar()) == -1) ; - return (char) character; + while (1) { + int err = prom_nbgetchar(buf); + if (!err) + break; + } } /* Blocking version of put character routine above. */ -void -prom_putchar(char c) +void prom_putchar(const char *buf) { - while(prom_nbputchar(c) == -1) ; + while (1) { + int err = prom_nbputchar(buf); + if (!err) + break; + } } diff --git a/arch/sparc/prom/console_64.c b/arch/sparc/prom/console_64.c index 33a8b275d6af..a9a575433ce9 100644 --- a/arch/sparc/prom/console_64.c +++ b/arch/sparc/prom/console_64.c @@ -18,41 +18,37 @@ extern int prom_stdin, prom_stdout; /* Non blocking get character from console input device, returns -1 * if no input was taken. This can be used for polling. */ -static int prom_nbgetchar(void) +static int prom_nbgetchar(char *buf) { unsigned long args[7]; - char inc; args[0] = (unsigned long) "read"; args[1] = 3; args[2] = 1; args[3] = (unsigned int) prom_stdin; - args[4] = (unsigned long) &inc; + args[4] = (unsigned long) buf; args[5] = 1; args[6] = (unsigned long) -1; p1275_cmd_direct(args); if (args[6] == 1) - return inc; + return 0; return -1; } /* Non blocking put character to console device, returns -1 if * unsuccessful. */ -static int prom_nbputchar(char c) +static int prom_nbputchar(const char *buf) { unsigned long args[7]; - char outc; - - outc = c; args[0] = (unsigned long) "write"; args[1] = 3; args[2] = 1; args[3] = (unsigned int) prom_stdout; - args[4] = (unsigned long) &outc; + args[4] = (unsigned long) buf; args[5] = 1; args[6] = (unsigned long) -1; @@ -65,17 +61,21 @@ static int prom_nbputchar(char c) } /* Blocking version of get character routine above. */ -char -prom_getchar(void) +void prom_getchar(char *buf) { - int character; - while((character = prom_nbgetchar()) == -1) ; - return (char) character; + while (1) { + int err = prom_nbgetchar(buf); + if (!err) + break; + } } /* Blocking version of put character routine above. */ -void -prom_putchar(char c) +void prom_putchar(const char *buf) { - prom_nbputchar(c); + while (1) { + int err = prom_nbputchar(buf); + if (!err) + break; + } } diff --git a/arch/sparc/prom/printf.c b/arch/sparc/prom/printf.c index ca869266b9f3..24031971f806 100644 --- a/arch/sparc/prom/printf.c +++ b/arch/sparc/prom/printf.c @@ -23,13 +23,14 @@ static char ppbuf[1024]; void notrace prom_write(const char *buf, unsigned int n) { - char ch; - - while (n != 0) { - --n; - if ((ch = *buf++) == '\n') - prom_putchar('\r'); - prom_putchar(ch); + while (n-- != 0) { + char ch = *buf; + if (ch == '\n') { + char tmp = '\r'; + prom_putchar(&tmp); + } + prom_putchar(buf); + buf++; } } -- cgit v1.2.3 From 84cf2fdf054b07ad33b71665a10816a3f60136ec Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 30 Nov 2010 14:53:05 -0800 Subject: sparc: Delete prom_*getchar(). [ Upstream commit 12c7a35ee6a1c605e740733f2cbd5b5079f09f0f ] Completely unused. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/sparc/include/asm/oplib_32.h | 5 ----- arch/sparc/include/asm/oplib_64.h | 5 ----- arch/sparc/prom/console_32.c | 41 --------------------------------------- arch/sparc/prom/console_64.c | 32 ------------------------------ 4 files changed, 83 deletions(-) diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h index 4d708b7d5528..3a2d3a60a117 100644 --- a/arch/sparc/include/asm/oplib_32.h +++ b/arch/sparc/include/asm/oplib_32.h @@ -102,11 +102,6 @@ extern int prom_getrev(void); /* Get the prom firmware revision. */ extern int prom_getprev(void); -/* Character operations to/from the console.... */ - -/* Blocking get character from console. */ -extern void prom_getchar(char *buf); - /* Blocking put character to console. */ extern void prom_putchar(const char *buf); diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h index 891a00b655ee..3636136c11ae 100644 --- a/arch/sparc/include/asm/oplib_64.h +++ b/arch/sparc/include/asm/oplib_64.h @@ -94,11 +94,6 @@ extern void prom_halt_power_off(void) __attribute__ ((noreturn)); */ extern unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size); -/* Character operations to/from the console.... */ - -/* Blocking get character from console. */ -extern void prom_getchar(char *buf); - /* Blocking put character to console. */ extern void prom_putchar(const char *buf); diff --git a/arch/sparc/prom/console_32.c b/arch/sparc/prom/console_32.c index 69c16bbf1f48..157019e29fd4 100644 --- a/arch/sparc/prom/console_32.c +++ b/arch/sparc/prom/console_32.c @@ -16,37 +16,6 @@ extern void restore_current(void); -/* Non blocking get character from console input device, returns -1 - * if no input was taken. This can be used for polling. - */ -static int prom_nbgetchar(char *buf) -{ - unsigned long flags; - int i = -1; - - spin_lock_irqsave(&prom_lock, flags); - switch(prom_vers) { - case PROM_V0: - i = (*(romvec->pv_nbgetchar))(); - if (i != -1) { - *buf = i; - i = 0; - } - break; - case PROM_V2: - case PROM_V3: - if ((*(romvec->pv_v2devops).v2_dev_read)(*romvec->pv_v2bootargs.fd_stdin, - buf, 0x1) == 1) - i = 0; - break; - default: - break; - }; - restore_current(); - spin_unlock_irqrestore(&prom_lock, flags); - return i; /* Ugh, we could spin forever on unsupported proms ;( */ -} - /* Non blocking put character to console device, returns -1 if * unsuccessful. */ @@ -74,16 +43,6 @@ static int prom_nbputchar(const char *buf) return i; /* Ugh, we could spin forever on unsupported proms ;( */ } -/* Blocking version of get character routine above. */ -void prom_getchar(char *buf) -{ - while (1) { - int err = prom_nbgetchar(buf); - if (!err) - break; - } -} - /* Blocking version of put character routine above. */ void prom_putchar(const char *buf) { diff --git a/arch/sparc/prom/console_64.c b/arch/sparc/prom/console_64.c index a9a575433ce9..0da88d10beff 100644 --- a/arch/sparc/prom/console_64.c +++ b/arch/sparc/prom/console_64.c @@ -15,28 +15,6 @@ extern int prom_stdin, prom_stdout; -/* Non blocking get character from console input device, returns -1 - * if no input was taken. This can be used for polling. - */ -static int prom_nbgetchar(char *buf) -{ - unsigned long args[7]; - - args[0] = (unsigned long) "read"; - args[1] = 3; - args[2] = 1; - args[3] = (unsigned int) prom_stdin; - args[4] = (unsigned long) buf; - args[5] = 1; - args[6] = (unsigned long) -1; - - p1275_cmd_direct(args); - - if (args[6] == 1) - return 0; - return -1; -} - /* Non blocking put character to console device, returns -1 if * unsuccessful. */ @@ -60,16 +38,6 @@ static int prom_nbputchar(const char *buf) return -1; } -/* Blocking version of get character routine above. */ -void prom_getchar(char *buf) -{ - while (1) { - int err = prom_nbgetchar(buf); - if (!err) - break; - } -} - /* Blocking version of put character routine above. */ void prom_putchar(const char *buf) { -- cgit v1.2.3 From bd5560f20742f1156c97838e51dbf655ff99058b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 30 Nov 2010 20:15:58 -0800 Subject: sparc: Write to prom console using indirect buffer. [ Upstream commit 595a251c0740785fd3c0d2156d78578c7479811e ] sparc64 systems have a restriction in that passing in buffer addressses above 4GB to prom calls is not reliable. We end up violating this when we do prom console writes, because we use an on-stack buffer to translate '\n' into '\r\n'. So instead, do this translation into an intermediate buffer, which is in the kernel image and thus below 4GB, then pass that to the PROM console write calls. On the 32-bit side we don't have to deal with any of these issues, so the new prom_console_write_buf() uses the existing prom_nbputchar() implementation. However we can now mark those routines static. Since the 64-bit side completely uses new code we can delete the putchar bits as they are now completely unused. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/sparc/include/asm/oplib_32.h | 4 ++-- arch/sparc/include/asm/oplib_64.h | 4 ++-- arch/sparc/prom/console_32.c | 14 ++++++++------ arch/sparc/prom/console_64.c | 27 +++++++++++++-------------- arch/sparc/prom/printf.c | 32 +++++++++++++++++++++++++++----- 5 files changed, 52 insertions(+), 29 deletions(-) diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h index 3a2d3a60a117..618a5bd4660d 100644 --- a/arch/sparc/include/asm/oplib_32.h +++ b/arch/sparc/include/asm/oplib_32.h @@ -102,8 +102,8 @@ extern int prom_getrev(void); /* Get the prom firmware revision. */ extern int prom_getprev(void); -/* Blocking put character to console. */ -extern void prom_putchar(const char *buf); +/* Write a buffer of characters to the console. */ +extern void prom_console_write_buf(const char *buf, int len); /* Prom's internal routines, don't use in kernel/boot code. */ extern void prom_printf(const char *fmt, ...); diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h index 3636136c11ae..209463d62626 100644 --- a/arch/sparc/include/asm/oplib_64.h +++ b/arch/sparc/include/asm/oplib_64.h @@ -94,8 +94,8 @@ extern void prom_halt_power_off(void) __attribute__ ((noreturn)); */ extern unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size); -/* Blocking put character to console. */ -extern void prom_putchar(const char *buf); +/* Write a buffer of characters to the console. */ +extern void prom_console_write_buf(const char *buf, int len); /* Prom's internal routines, don't use in kernel/boot code. */ extern void prom_printf(const char *fmt, ...); diff --git a/arch/sparc/prom/console_32.c b/arch/sparc/prom/console_32.c index 157019e29fd4..48863108a44c 100644 --- a/arch/sparc/prom/console_32.c +++ b/arch/sparc/prom/console_32.c @@ -43,12 +43,14 @@ static int prom_nbputchar(const char *buf) return i; /* Ugh, we could spin forever on unsupported proms ;( */ } -/* Blocking version of put character routine above. */ -void prom_putchar(const char *buf) +void prom_console_write_buf(const char *buf, int len) { - while (1) { - int err = prom_nbputchar(buf); - if (!err) - break; + while (len) { + int n = prom_nbputchar(buf); + if (n) + continue; + len--; + buf++; } } + diff --git a/arch/sparc/prom/console_64.c b/arch/sparc/prom/console_64.c index 0da88d10beff..ed39e75828bd 100644 --- a/arch/sparc/prom/console_64.c +++ b/arch/sparc/prom/console_64.c @@ -15,35 +15,34 @@ extern int prom_stdin, prom_stdout; -/* Non blocking put character to console device, returns -1 if - * unsuccessful. - */ -static int prom_nbputchar(const char *buf) +static int __prom_console_write_buf(const char *buf, int len) { unsigned long args[7]; + int ret; args[0] = (unsigned long) "write"; args[1] = 3; args[2] = 1; args[3] = (unsigned int) prom_stdout; args[4] = (unsigned long) buf; - args[5] = 1; + args[5] = (unsigned int) len; args[6] = (unsigned long) -1; p1275_cmd_direct(args); - if (args[6] == 1) - return 0; - else + ret = (int) args[6]; + if (ret < 0) return -1; + return ret; } -/* Blocking version of put character routine above. */ -void prom_putchar(const char *buf) +void prom_console_write_buf(const char *buf, int len) { - while (1) { - int err = prom_nbputchar(buf); - if (!err) - break; + while (len) { + int n = __prom_console_write_buf(buf, len); + if (n < 0) + continue; + len -= n; + buf += len; } } diff --git a/arch/sparc/prom/printf.c b/arch/sparc/prom/printf.c index 24031971f806..d9682f06b3b0 100644 --- a/arch/sparc/prom/printf.c +++ b/arch/sparc/prom/printf.c @@ -15,23 +15,45 @@ #include #include +#include #include #include +#define CONSOLE_WRITE_BUF_SIZE 1024 + static char ppbuf[1024]; +static char console_write_buf[CONSOLE_WRITE_BUF_SIZE]; +static DEFINE_RAW_SPINLOCK(console_write_lock); void notrace prom_write(const char *buf, unsigned int n) { + unsigned int dest_len; + unsigned long flags; + char *dest; + + dest = console_write_buf; + raw_spin_lock_irqsave(&console_write_lock, flags); + + dest_len = 0; while (n-- != 0) { - char ch = *buf; + char ch = *buf++; if (ch == '\n') { - char tmp = '\r'; - prom_putchar(&tmp); + *dest++ = '\r'; + dest_len++; + } + *dest++ = ch; + dest_len++; + if (dest_len >= CONSOLE_WRITE_BUF_SIZE - 1) { + prom_console_write_buf(console_write_buf, dest_len); + dest = console_write_buf; + dest_len = 0; } - prom_putchar(buf); - buf++; } + if (dest_len) + prom_console_write_buf(console_write_buf, dest_len); + + raw_spin_unlock_irqrestore(&console_write_lock, flags); } void notrace prom_printf(const char *fmt, ...) -- cgit v1.2.3 From 433591a15ed9237eb89ae123334ae8389e0e95a5 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 12 Nov 2010 13:35:00 -0800 Subject: tcp: Don't change unlocked socket state in tcp_v4_err(). [ Upstream commit 8f49c2703b33519aaaccc63f571b465b9d2b3a2d ] Alexey Kuznetsov noticed a regression introduced by commit f1ecd5d9e7366609d640ff4040304ea197fbc618 ("Revert Backoff [v3]: Revert RTO on ICMP destination unreachable") The RTO and timer modification code added to tcp_v4_err() doesn't check sock_owned_by_user(), which if true means we don't have exclusive access to the socket and therefore cannot modify it's critical state. Just skip this new code block if sock_owned_by_user() is true and eliminate the now superfluous sock_owned_by_user() code block contained within. Reported-by: Alexey Kuznetsov Signed-off-by: David S. Miller Signed-off-by: Andi Kleen CC: Damian Lukowski Acked-by: Eric Dumazet Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_ipv4.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index fe193e53af44..163a5c1795db 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -411,6 +411,9 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) !icsk->icsk_backoff) break; + if (sock_owned_by_user(sk)) + break; + icsk->icsk_backoff--; inet_csk(sk)->icsk_rto = __tcp_set_rto(tp) << icsk->icsk_backoff; @@ -425,11 +428,6 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) if (remaining) { inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, remaining, TCP_RTO_MAX); - } else if (sock_owned_by_user(sk)) { - /* RTO revert clocked out retransmission, - * but socket is locked. Will defer. */ - inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, - HZ/20, TCP_RTO_MAX); } else { /* RTO revert clocked out retransmission. * Will retransmit now */ -- cgit v1.2.3 From 0575b918879bdc762d41b9d8b322a3bfcb7b29e0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Nov 2010 21:35:37 -0800 Subject: tcp: Increase TCP_MAXSEG socket option minimum. [ Upstream commit 7a1abd08d52fdeddb3e9a5a33f2f15cc6a5674d2 ] As noted by Steve Chen, since commit f5fff5dc8a7a3f395b0525c02ba92c95d42b7390 ("tcp: advertise MSS requested by user") we can end up with a situation where tcp_select_initial_window() does a divide by a zero (or even negative) mss value. The problem is that sometimes we effectively subtract TCPOLEN_TSTAMP_ALIGNED and/or TCPOLEN_MD5SIG_ALIGNED from the mss. Fix this by increasing the minimum from 8 to 64. Reported-by: Steve Chen Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ipv4/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index dc6cffa8a9cf..21a257c4cb3c 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2235,7 +2235,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, /* Values greater than interface MTU won't take effect. However * at the point when this call is done we typically don't yet * know which interface is going to be used */ - if (val < 8 || val > MAX_TCP_WINDOW) { + if (val < 64 || val > MAX_TCP_WINDOW) { err = -EINVAL; break; } -- cgit v1.2.3 From 98fd120a33e16892e305107f33ab6525b7751421 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 24 Nov 2010 11:47:22 -0800 Subject: tcp: Make TCP_MAXSEG minimum more correct. [ Upstream commit c39508d6f118308355468314ff414644115a07f3 ] Use TCP_MIN_MSS instead of constant 64. Reported-by: Min Zhang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ipv4/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 21a257c4cb3c..673fbe702500 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2235,7 +2235,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, /* Values greater than interface MTU won't take effect. However * at the point when this call is done we typically don't yet * know which interface is going to be used */ - if (val < 64 || val > MAX_TCP_WINDOW) { + if (val < TCP_MIN_MSS || val > MAX_TCP_WINDOW) { err = -EINVAL; break; } -- cgit v1.2.3 From 9a4b8e0c3674f6506c5a2b3c7ac5ea37e297c0a0 Mon Sep 17 00:00:00 2001 From: Nandita Dukkipati Date: Fri, 3 Dec 2010 13:33:44 +0000 Subject: tcp: Bug fix in initialization of receive window. [ Upstream commit b1afde60f2b9ee8444fba4e012dc99a3b28d224d ] The bug has to do with boundary checks on the initial receive window. If the initial receive window falls between init_cwnd and the receive window specified by the user, the initial window is incorrectly brought down to init_cwnd. The correct behavior is to allow it to remain unchanged. Signed-off-by: Nandita Dukkipati Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ipv4/tcp_output.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 7ed9dc1042d1..0c93b0b98b14 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -237,11 +237,10 @@ void tcp_select_initial_window(int __space, __u32 mss, /* when initializing use the value from init_rcv_wnd * rather than the default from above */ - if (init_rcv_wnd && - (*rcv_wnd > init_rcv_wnd * mss)) - *rcv_wnd = init_rcv_wnd * mss; - else if (*rcv_wnd > init_cwnd * mss) - *rcv_wnd = init_cwnd * mss; + if (init_rcv_wnd) + *rcv_wnd = min(*rcv_wnd, init_rcv_wnd * mss); + else + *rcv_wnd = min(*rcv_wnd, init_cwnd * mss); } /* Set the clamp no higher than max representable value */ -- cgit v1.2.3 From d98450d683e13c6af7b5219af44cea2671dc07ea Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 7 Dec 2010 12:03:55 +0000 Subject: tcp: avoid a possible divide by zero [ Upstream commit ad9f4f50fe9288bbe65b7dfd76d8820afac6a24c ] sysctl_tcp_tso_win_divisor might be set to zero while one cpu runs in tcp_tso_should_defer(). Make sure we dont allow a divide by zero by reading sysctl_tcp_tso_win_divisor exactly once. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ipv4/tcp_output.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 0c93b0b98b14..a01a6adc8609 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1516,6 +1516,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb) struct tcp_sock *tp = tcp_sk(sk); const struct inet_connection_sock *icsk = inet_csk(sk); u32 send_win, cong_win, limit, in_flight; + int win_divisor; if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) goto send_now; @@ -1547,13 +1548,14 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb) if ((skb != tcp_write_queue_tail(sk)) && (limit >= skb->len)) goto send_now; - if (sysctl_tcp_tso_win_divisor) { + win_divisor = ACCESS_ONCE(sysctl_tcp_tso_win_divisor); + if (win_divisor) { u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache); /* If at least some fraction of a window is available, * just use it. */ - chunk /= sysctl_tcp_tso_win_divisor; + chunk /= win_divisor; if (limit >= chunk) goto send_now; } else { -- cgit v1.2.3 From 5f8d6ba121ac7b0651396e8ce71c6fea4befca45 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 7 Dec 2010 12:20:47 +0000 Subject: tcp: protect sysctl_tcp_cookie_size reads [ Upstream commit f19872575ff7819a3723154657a497d9bca66b33 ] Make sure sysctl_tcp_cookie_size is read once in tcp_cookie_size_check(), or we might return an illegal value to caller if sysctl_tcp_cookie_size is changed by another cpu. Signed-off-by: Eric Dumazet Signed-off-by: Andi Kleen Cc: Ben Hutchings Cc: William Allen Simpson Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_output.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index a01a6adc8609..1df0d17467fc 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -390,27 +390,30 @@ struct tcp_out_options { */ static u8 tcp_cookie_size_check(u8 desired) { - if (desired > 0) { + int cookie_size; + + if (desired > 0) /* previously specified */ return desired; - } - if (sysctl_tcp_cookie_size <= 0) { + + cookie_size = ACCESS_ONCE(sysctl_tcp_cookie_size); + if (cookie_size <= 0) /* no default specified */ return 0; - } - if (sysctl_tcp_cookie_size <= TCP_COOKIE_MIN) { + + if (cookie_size <= TCP_COOKIE_MIN) /* value too small, specify minimum */ return TCP_COOKIE_MIN; - } - if (sysctl_tcp_cookie_size >= TCP_COOKIE_MAX) { + + if (cookie_size >= TCP_COOKIE_MAX) /* value too large, specify maximum */ return TCP_COOKIE_MAX; - } - if (0x1 & sysctl_tcp_cookie_size) { + + if (cookie_size & 1) /* 8-bit multiple, illegal, fix it */ - return (u8)(sysctl_tcp_cookie_size + 0x1); - } - return (u8)sysctl_tcp_cookie_size; + cookie_size++; + + return (u8)cookie_size; } /* Write previously computed TCP options to the packet. -- cgit v1.2.3 From 4fef93a724a0294bc372e3f0049b5f9dfa09e44e Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Wed, 17 Nov 2010 11:55:08 -0800 Subject: 8139cp: fix checksum broken [ Upstream commit 24b7ea9f6c9787fad885442ed0cc010f1aa69cca ] I am not family with RealTek RTL-8139C+ series 10/100 PCI Ethernet driver. I try to guess the meaning of RxProtoIP and IPFail. RxProtoIP stands for received IPv4 packet that upper protocol is not tcp and udp. !(status & IPFail) is true means that driver correctly to check checksum in IPv4 header. If these are right, driver will set ip_summed with CHECKSUM_UNNECESSARY for other upper protocol, e.g. sctp, igmp protocol. This will cause protocol stack ignores checksum check for packets with invalid checksum. This patch is only compile-test. Signed-off-by: Shan Wei Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/8139cp.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 284a5f4a63ac..7b1b2569a2f6 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -490,13 +490,11 @@ static inline unsigned int cp_rx_csum_ok (u32 status) { unsigned int protocol = (status >> 16) & 0x3; - if (likely((protocol == RxProtoTCP) && (!(status & TCPFail)))) + if (((protocol == RxProtoTCP) && !(status & TCPFail)) || + ((protocol == RxProtoUDP) && !(status & UDPFail))) return 1; - else if ((protocol == RxProtoUDP) && (!(status & UDPFail))) - return 1; - else if ((protocol == RxProtoIP) && (!(status & IPFail))) - return 1; - return 0; + else + return 0; } static int cp_rx_poll(struct napi_struct *napi, int budget) -- cgit v1.2.3 From b628317b1d1a58bc5722c982fce2729120438734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fran=C3=A7ois=20romieu?= Date: Mon, 8 Nov 2010 13:23:58 +0000 Subject: r8169: fix sleeping while holding spinlock. [ Upstream commit ea80907ff066edd1dd43c5fe90ae6677d15e6384 ] As device_set_wakeup_enable can now sleep, move the call to outside the critical section. Signed-off-by: Daniel J Blueman Acked-by: Rafael J. Wysocki Acked-by: Andrew Hendry Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/r8169.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index b99dd04710f2..857ecafefd2c 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -855,10 +855,10 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) else tp->features &= ~RTL_FEATURE_WOL; __rtl8169_set_wol(tp, wol->wolopts); - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - spin_unlock_irq(&tp->lock); + device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); + return 0; } -- cgit v1.2.3 From 4d6d4fae2b988f48b94d93bc398fdf353463ec40 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 24 Nov 2010 09:15:27 -0800 Subject: af_unix: limit unix_tot_inflight [ Upstream commit 9915672d41273f5b77f1b3c29b391ffb7732b84b ] Vegard Nossum found a unix socket OOM was possible, posting an exploit program. My analysis is we can eat all LOWMEM memory before unix_gc() being called from unix_release_sock(). Moreover, the thread blocked in unix_gc() can consume huge amount of time to perform cleanup because of huge working set. One way to handle this is to have a sensible limit on unix_tot_inflight, tested from wait_for_unix_gc() and to force a call to unix_gc() if this limit is hit. This solves the OOM and also reduce overall latencies, and should not slowdown normal workloads. Reported-by: Vegard Nossum Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/unix/garbage.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/unix/garbage.c b/net/unix/garbage.c index c8df6fda0b1f..40df93d1cf35 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -259,9 +259,16 @@ static void inc_inflight_move_tail(struct unix_sock *u) } static bool gc_in_progress = false; +#define UNIX_INFLIGHT_TRIGGER_GC 16000 void wait_for_unix_gc(void) { + /* + * If number of inflight sockets is insane, + * force a garbage collect right now. + */ + if (unix_tot_inflight > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress) + unix_gc(); wait_event(unix_gc_wait, gc_in_progress == false); } -- cgit v1.2.3 From cab9e9848b9a8283b0504a2d7c435a9f5ba026de Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 13 Jun 2010 03:32:34 +0000 Subject: scm: Capture the full credentials of the scm sender. Upstream commit 257b5358b32f17e0603b6ff57b13610b0e02348f Start capturing not only the userspace pid, uid and gid values of the sending process but also the struct pid and struct cred of the sending process as well. This is in preparation for properly supporting SCM_CREDENTIALS for sockets that have different uid and/or pid namespaces at the different ends. Signed-off-by: Eric W. Biederman Acked-by: Serge E. Hallyn Signed-off-by: David S. Miller Signed-off-by: Andi Kleen --- include/net/scm.h | 28 ++++++++++++++++++++++++---- net/core/scm.c | 24 ++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/include/net/scm.h b/include/net/scm.h index 8360e47aa7e3..096286d05331 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -19,6 +19,8 @@ struct scm_fp_list { }; struct scm_cookie { + struct pid *pid; /* Skb credentials */ + const struct cred *cred; struct ucred creds; /* Skb credentials */ struct scm_fp_list *fp; /* Passed files */ #ifdef CONFIG_SECURITY_NETWORK @@ -42,8 +44,27 @@ static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_co { } #endif /* CONFIG_SECURITY_NETWORK */ +static __inline__ void scm_set_cred(struct scm_cookie *scm, + struct pid *pid, const struct cred *cred) +{ + scm->pid = get_pid(pid); + scm->cred = get_cred(cred); + cred_to_ucred(pid, cred, &scm->creds); +} + +static __inline__ void scm_destroy_cred(struct scm_cookie *scm) +{ + put_pid(scm->pid); + scm->pid = NULL; + + if (scm->cred) + put_cred(scm->cred); + scm->cred = NULL; +} + static __inline__ void scm_destroy(struct scm_cookie *scm) { + scm_destroy_cred(scm); if (scm && scm->fp) __scm_destroy(scm); } @@ -51,10 +72,7 @@ static __inline__ void scm_destroy(struct scm_cookie *scm) static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) { - struct task_struct *p = current; - scm->creds.uid = current_uid(); - scm->creds.gid = current_gid(); - scm->creds.pid = task_tgid_vnr(p); + scm_set_cred(scm, task_tgid(current), current_cred()); scm->fp = NULL; unix_get_peersec_dgram(sock, scm); if (msg->msg_controllen <= 0) @@ -96,6 +114,8 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg, if (test_bit(SOCK_PASSCRED, &sock->flags)) put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds); + scm_destroy_cred(scm); + scm_passec(sock, msg, scm); if (!scm->fp) diff --git a/net/core/scm.c b/net/core/scm.c index b88f6f9d0b97..681c976307b5 100644 --- a/net/core/scm.c +++ b/net/core/scm.c @@ -170,6 +170,30 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p) err = scm_check_creds(&p->creds); if (err) goto error; + + if (pid_vnr(p->pid) != p->creds.pid) { + struct pid *pid; + err = -ESRCH; + pid = find_get_pid(p->creds.pid); + if (!pid) + goto error; + put_pid(p->pid); + p->pid = pid; + } + + if ((p->cred->euid != p->creds.uid) || + (p->cred->egid != p->creds.gid)) { + struct cred *cred; + err = -ENOMEM; + cred = prepare_creds(); + if (!cred) + goto error; + + cred->uid = cred->euid = p->creds.uid; + cred->gid = cred->egid = p->creds.uid; + put_cred(p->cred); + p->cred = cred; + } break; default: goto error; -- cgit v1.2.3 From 76319701efb717e4a159f4cdb159646c6862e6a0 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 13 Jun 2010 03:34:33 +0000 Subject: af_unix: Allow credentials to work across user and pid namespaces. Upstream commit 7361c36c5224519b258219fe3d0e8abc865d8134 In unix_skb_parms store pointers to struct pid and struct cred instead of raw uid, gid, and pid values, then translate the credentials on reception into values that are meaningful in the receiving processes namespaces. Signed-off-by: Eric W. Biederman Acked-by: Pavel Emelyanov Signed-off-by: David S. Miller Signed-off-by: Andi Kleen --- include/net/af_unix.h | 4 ++-- net/unix/af_unix.c | 53 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 20725e213aee..90c9e2872f27 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -23,7 +23,8 @@ struct unix_address { }; struct unix_skb_parms { - struct ucred creds; /* Skb credentials */ + struct pid *pid; /* Skb credentials */ + const struct cred *cred; struct scm_fp_list *fp; /* Passed files */ #ifdef CONFIG_SECURITY_NETWORK u32 secid; /* Security ID */ @@ -31,7 +32,6 @@ struct unix_skb_parms { }; #define UNIXCB(skb) (*(struct unix_skb_parms *)&((skb)->cb)) -#define UNIXCREDS(skb) (&UNIXCB((skb)).creds) #define UNIXSID(skb) (&UNIXCB((skb)).secid) #define unix_state_lock(s) spin_lock(&unix_sk(s)->lock) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 617bea46486d..c9da1fce643e 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1306,18 +1306,20 @@ static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb) int i; scm->fp = UNIXCB(skb).fp; - skb->destructor = sock_wfree; UNIXCB(skb).fp = NULL; for (i = scm->fp->count-1; i >= 0; i--) unix_notinflight(scm->fp->fp[i]); } -static void unix_destruct_fds(struct sk_buff *skb) +static void unix_destruct_scm(struct sk_buff *skb) { struct scm_cookie scm; memset(&scm, 0, sizeof(scm)); - unix_detach_fds(&scm, skb); + scm.pid = UNIXCB(skb).pid; + scm.cred = UNIXCB(skb).cred; + if (UNIXCB(skb).fp) + unix_detach_fds(&scm, skb); /* Alas, it calls VFS */ /* So fscking what? fput() had been SMP-safe since the last Summer */ @@ -1340,10 +1342,22 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) for (i = scm->fp->count-1; i >= 0; i--) unix_inflight(scm->fp->fp[i]); - skb->destructor = unix_destruct_fds; return 0; } +static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds) +{ + int err = 0; + UNIXCB(skb).pid = get_pid(scm->pid); + UNIXCB(skb).cred = get_cred(scm->cred); + UNIXCB(skb).fp = NULL; + if (scm->fp && send_fds) + err = unix_attach_fds(scm, skb); + + skb->destructor = unix_destruct_scm; + return err; +} + /* * Send AF_UNIX data. */ @@ -1400,12 +1414,9 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, if (skb == NULL) goto out; - memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); - if (siocb->scm->fp) { - err = unix_attach_fds(siocb->scm, skb); - if (err) - goto out_free; - } + err = unix_scm_to_skb(siocb->scm, skb, true); + if (err) + goto out_free; unix_get_secdata(siocb->scm, skb); skb_reset_transport_header(skb); @@ -1575,16 +1586,14 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, */ size = min_t(int, size, skb_tailroom(skb)); - memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); + /* Only send the fds in the first buffer */ - if (siocb->scm->fp && !fds_sent) { - err = unix_attach_fds(siocb->scm, skb); - if (err) { - kfree_skb(skb); - goto out_err; - } - fds_sent = true; + err = unix_scm_to_skb(siocb->scm, skb, !fds_sent); + if (err) { + kfree_skb(skb); + goto out_err; } + fds_sent = true; err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); if (err) { @@ -1701,7 +1710,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, siocb->scm = &tmp_scm; memset(&tmp_scm, 0, sizeof(tmp_scm)); } - siocb->scm->creds = *UNIXCREDS(skb); + scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); unix_set_secdata(siocb->scm, skb); if (!(flags & MSG_PEEK)) { @@ -1850,14 +1859,14 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, if (check_creds) { /* Never glue messages from different writers */ - if (memcmp(UNIXCREDS(skb), &siocb->scm->creds, - sizeof(siocb->scm->creds)) != 0) { + if ((UNIXCB(skb).pid != siocb->scm->pid) || + (UNIXCB(skb).cred != siocb->scm->cred)) { skb_queue_head(&sk->sk_receive_queue, skb); break; } } else { /* Copy credentials */ - siocb->scm->creds = *UNIXCREDS(skb); + scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); check_creds = 1; } -- cgit v1.2.3 From 7d77e1c063cba215c6217e0fca3bbd4f53ec7f4d Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 13 Jun 2010 03:28:03 +0000 Subject: user_ns: Introduce user_nsmap_uid and user_ns_map_gid. Upstream commit 5c1469de7545a35a16ff2b902e217044a7d2f8a5 Define what happens when a we view a uid from one user_namespace in another user_namepece. - If the user namespaces are the same no mapping is necessary. - For most cases of difference use overflowuid and overflowgid, the uid and gid currently used for 16bit apis when we have a 32bit uid that does fit in 16bits. Effectively the situation is the same, we want to return a uid or gid that is not assigned to any user. - For the case when we happen to be mapping the uid or gid of the creator of the target user namespace use uid 0 and gid as confusing that user with root is not a problem. Signed-off-by: Eric W. Biederman Acked-by: Serge E. Hallyn Signed-off-by: David S. Miller Signed-off-by: Andi Kleen --- include/linux/user_namespace.h | 14 ++++++++++++++ kernel/user_namespace.c | 44 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index cc4f45361dbb..8178156711f9 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -36,6 +36,9 @@ static inline void put_user_ns(struct user_namespace *ns) kref_put(&ns->kref, free_user_ns); } +uid_t user_ns_map_uid(struct user_namespace *to, const struct cred *cred, uid_t uid); +gid_t user_ns_map_gid(struct user_namespace *to, const struct cred *cred, gid_t gid); + #else static inline struct user_namespace *get_user_ns(struct user_namespace *ns) @@ -52,6 +55,17 @@ static inline void put_user_ns(struct user_namespace *ns) { } +static inline uid_t user_ns_map_uid(struct user_namespace *to, + const struct cred *cred, uid_t uid) +{ + return uid; +} +static inline gid_t user_ns_map_gid(struct user_namespace *to, + const struct cred *cred, gid_t gid) +{ + return gid; +} + #endif #endif /* _LINUX_USER_H */ diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index b2d70d38dff4..25915832291a 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -9,6 +9,7 @@ #include #include #include +#include #include /* @@ -82,3 +83,46 @@ void free_user_ns(struct kref *kref) schedule_work(&ns->destroyer); } EXPORT_SYMBOL(free_user_ns); + +uid_t user_ns_map_uid(struct user_namespace *to, const struct cred *cred, uid_t uid) +{ + struct user_namespace *tmp; + + if (likely(to == cred->user->user_ns)) + return uid; + + + /* Is cred->user the creator of the target user_ns + * or the creator of one of it's parents? + */ + for ( tmp = to; tmp != &init_user_ns; + tmp = tmp->creator->user_ns ) { + if (cred->user == tmp->creator) { + return (uid_t)0; + } + } + + /* No useful relationship so no mapping */ + return overflowuid; +} + +gid_t user_ns_map_gid(struct user_namespace *to, const struct cred *cred, gid_t gid) +{ + struct user_namespace *tmp; + + if (likely(to == cred->user->user_ns)) + return gid; + + /* Is cred->user the creator of the target user_ns + * or the creator of one of it's parents? + */ + for ( tmp = to; tmp != &init_user_ns; + tmp = tmp->creator->user_ns ) { + if (cred->user == tmp->creator) { + return (gid_t)0; + } + } + + /* No useful relationship so no mapping */ + return overflowgid; +} -- cgit v1.2.3 From afa01a2cc021a5f03f02364bb867af3114395304 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 13 Jun 2010 03:28:59 +0000 Subject: sock: Introduce cred_to_ucred Upstream commit 3f551f9436c05a3b5eccdd6e94733df5bb98d2a5 To keep the coming code clear and to allow both the sock code and the scm code to share the logic introduce a fuction to translate from struct cred to struct ucred. Signed-off-by: Eric W. Biederman Acked-by: Pavel Emelyanov Signed-off-by: David S. Miller Signed-off-by: Andi Kleen --- include/linux/socket.h | 5 +++++ net/core/sock.c | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/linux/socket.h b/include/linux/socket.h index 032a19eb61b1..a2fada9becb6 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -24,6 +24,9 @@ struct __kernel_sockaddr_storage { #include /* pid_t */ #include /* __user */ +struct pid; +struct cred; + #define __sockaddr_check_size(size) \ BUILD_BUG_ON(((size) > sizeof(struct __kernel_sockaddr_storage))) @@ -309,6 +312,8 @@ struct ucred { #define IPX_TYPE 1 #ifdef __KERNEL__ +extern void cred_to_ucred(struct pid *pid, const struct cred *cred, struct ucred *ucred); + extern int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); extern int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, int offset, int len); diff --git a/net/core/sock.c b/net/core/sock.c index 2cf7f9f7e775..50197eb9314f 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -110,6 +110,7 @@ #include #include #include +#include #include #include @@ -749,6 +750,19 @@ set_rcvbuf: EXPORT_SYMBOL(sock_setsockopt); +void cred_to_ucred(struct pid *pid, const struct cred *cred, + struct ucred *ucred) +{ + ucred->pid = pid_vnr(pid); + ucred->uid = ucred->gid = -1; + if (cred) { + struct user_namespace *current_ns = current_user_ns(); + + ucred->uid = user_ns_map_uid(current_ns, cred, cred->euid); + ucred->gid = user_ns_map_gid(current_ns, cred, cred->egid); + } +} + int sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { -- cgit v1.2.3 From 993788a53aa0c8efd14922e799e0764220fa5a33 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 16 Jun 2010 16:18:25 -0700 Subject: net: Export cred_to_ucred to modules. Upstream commit 3924773a5a82622167524bdd48799dc0452c57f8 AF_UNIX references this, and can be built as a module, so... Signed-off-by: David S. Miller Signed-off-by: Andi Kleen --- net/core/sock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/sock.c b/net/core/sock.c index 50197eb9314f..e73470056d5b 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -762,6 +762,7 @@ void cred_to_ucred(struct pid *pid, const struct cred *cred, ucred->gid = user_ns_map_gid(current_ns, cred, cred->egid); } } +EXPORT_SYMBOL_GPL(cred_to_ucred); int sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) -- cgit v1.2.3 From 80260452aed3ebb509e9cf6f77b5a1dd922f60ef Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 25 Nov 2010 04:11:39 +0000 Subject: af_unix: limit recursion level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 25888e30319f8896fc656fc68643e6a078263060 ] Its easy to eat all kernel memory and trigger NMI watchdog, using an exploit program that queues unix sockets on top of others. lkml ref : http://lkml.org/lkml/2010/11/25/8 This mechanism is used in applications, one choice we have is to have a recursion limit. Other limits might be needed as well (if we queue other types of files), since the passfd mechanism is currently limited by socket receive queue sizes only. Add a recursion_level to unix socket, allowing up to 4 levels. Each time we send an unix socket through sendfd mechanism, we copy its recursion level (plus one) to receiver. This recursion level is cleared when socket receive queue is emptied. Reported-by: Марк Коренберг Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/net/af_unix.h | 2 ++ net/unix/af_unix.c | 37 ++++++++++++++++++++++++++++++++----- net/unix/garbage.c | 2 +- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 90c9e2872f27..18e5c3f67580 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -10,6 +10,7 @@ extern void unix_inflight(struct file *fp); extern void unix_notinflight(struct file *fp); extern void unix_gc(void); extern void wait_for_unix_gc(void); +extern struct sock *unix_get_socket(struct file *filp); #define UNIX_HASH_SIZE 256 @@ -56,6 +57,7 @@ struct unix_sock { spinlock_t lock; unsigned int gc_candidate : 1; unsigned int gc_maybe_cycle : 1; + unsigned char recursion_level; struct socket_wq peer_wq; }; #define unix_sk(__sk) ((struct unix_sock *)__sk) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index c9da1fce643e..d63e7a206142 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1327,9 +1327,25 @@ static void unix_destruct_scm(struct sk_buff *skb) sock_wfree(skb); } +#define MAX_RECURSION_LEVEL 4 + static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) { int i; + unsigned char max_level = 0; + int unix_sock_count = 0; + + for (i = scm->fp->count - 1; i >= 0; i--) { + struct sock *sk = unix_get_socket(scm->fp->fp[i]); + + if (sk) { + unix_sock_count++; + max_level = max(max_level, + unix_sk(sk)->recursion_level); + } + } + if (unlikely(max_level > MAX_RECURSION_LEVEL)) + return -ETOOMANYREFS; /* * Need to duplicate file references for the sake of garbage @@ -1340,9 +1356,11 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) if (!UNIXCB(skb).fp) return -ENOMEM; - for (i = scm->fp->count-1; i >= 0; i--) - unix_inflight(scm->fp->fp[i]); - return 0; + if (unix_sock_count) { + for (i = scm->fp->count - 1; i >= 0; i--) + unix_inflight(scm->fp->fp[i]); + } + return max_level; } static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds) @@ -1377,6 +1395,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, struct sk_buff *skb; long timeo; struct scm_cookie tmp_scm; + int max_level; if (NULL == siocb->scm) siocb->scm = &tmp_scm; @@ -1415,8 +1434,9 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, goto out; err = unix_scm_to_skb(siocb->scm, skb, true); - if (err) + if (err < 0) goto out_free; + max_level = err + 1; unix_get_secdata(siocb->scm, skb); skb_reset_transport_header(skb); @@ -1496,6 +1516,8 @@ restart: } skb_queue_tail(&other->sk_receive_queue, skb); + if (max_level > unix_sk(other)->recursion_level) + unix_sk(other)->recursion_level = max_level; unix_state_unlock(other); other->sk_data_ready(other, len); sock_put(other); @@ -1526,6 +1548,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, int sent = 0; struct scm_cookie tmp_scm; bool fds_sent = false; + int max_level; if (NULL == siocb->scm) siocb->scm = &tmp_scm; @@ -1589,10 +1612,11 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, /* Only send the fds in the first buffer */ err = unix_scm_to_skb(siocb->scm, skb, !fds_sent); - if (err) { + if (err < 0) { kfree_skb(skb); goto out_err; } + max_level = err + 1; fds_sent = true; err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); @@ -1608,6 +1632,8 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, goto pipe_err_free; skb_queue_tail(&other->sk_receive_queue, skb); + if (max_level > unix_sk(other)->recursion_level) + unix_sk(other)->recursion_level = max_level; unix_state_unlock(other); other->sk_data_ready(other, size); sent += size; @@ -1824,6 +1850,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, unix_state_lock(sk); skb = skb_dequeue(&sk->sk_receive_queue); if (skb == NULL) { + unix_sk(sk)->recursion_level = 0; if (copied >= target) goto unlock; diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 40df93d1cf35..f89f83bf828e 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -96,7 +96,7 @@ static DECLARE_WAIT_QUEUE_HEAD(unix_gc_wait); unsigned int unix_tot_inflight; -static struct sock *unix_get_socket(struct file *filp) +struct sock *unix_get_socket(struct file *filp) { struct sock *u_sock = NULL; struct inode *inode = filp->f_path.dentry->d_inode; -- cgit v1.2.3 From 3a734d802e9db68675d947def39b697d816b8232 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Wed, 10 Nov 2010 10:14:33 -0800 Subject: net: ax25: fix information leak to userland [ Upstream commit fe10ae53384e48c51996941b7720ee16995cbcb7 ] Sometimes ax25_getname() doesn't initialize all members of fsa_digipeater field of fsa struct, also the struct has padding bytes between sax25_call and sax25_ndigis fields. This structure is then copied to userland. It leads to leaking of contents of kernel stack memory. Signed-off-by: Vasiliy Kulikov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ax25/af_ax25.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index cfdfd7e2a172..6e2371a493b7 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1392,6 +1392,7 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, ax25_cb *ax25; int err = 0; + memset(fsa, 0, sizeof(fsa)); lock_sock(sk); ax25 = ax25_sk(sk); @@ -1403,7 +1404,6 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, fsa->fsa_ax25.sax25_family = AF_AX25; fsa->fsa_ax25.sax25_call = ax25->dest_addr; - fsa->fsa_ax25.sax25_ndigis = 0; if (ax25->digipeat != NULL) { ndigi = ax25->digipeat->ndigi; -- cgit v1.2.3 From b89a67e20a5ea68eb607d38c7eb2cf78b29f897f Mon Sep 17 00:00:00 2001 From: Joe Jin Date: Mon, 6 Dec 2010 03:00:59 +0000 Subject: driver/net/benet: fix be_cmd_multicast_set() memcpy bug [ Upstream commit 3fd40d0ceac9c234243730f4d7a6ffdb2fd3023a ] Regarding benet be_cmd_multicast_set() function, now using netdev_for_each_mc_addr() helper for mac address copy, but when copying to req->mac[] did not increase of the index. Cc: Sathya Perla Cc: Subbu Seetharaman Cc: Sarveshwar Bandi Cc: Ajit Khaparde Signed-off-by: Joe Jin Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/benet/be_cmds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index b9ad799c719f..2d6b77cf38ac 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -1176,7 +1176,7 @@ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, i = 0; netdev_for_each_mc_addr(ha, netdev) - memcpy(req->mac[i].byte, ha->addr, ETH_ALEN); + memcpy(req->mac[i++].byte, ha->addr, ETH_ALEN); } else { req->promiscuous = 1; } -- cgit v1.2.3 From f69a92aa29a6c15ccad53832a55c1418568f5977 Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Fri, 10 Dec 2010 18:54:11 +0000 Subject: bonding: Fix slave selection bug. [ Upstream commit af3e5bd5f650163c2e12297f572910a1af1b8236 ] The returned slave is incorrect, if the net device under check is not charged yet by the master. Signed-off-by: Hillf Danton Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/bonding/bonding.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 2aa336720591..35cf49144249 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -235,11 +235,11 @@ static inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct n bond_for_each_slave(bond, slave, i) { if (slave->dev == slave_dev) { - break; + return slave; } } - return slave; + return 0; } static inline struct bonding *bond_get_bond_by_slave(struct slave *slave) -- cgit v1.2.3 From 419765ea4d221ddb9f41558eb5948c7c838f34ba Mon Sep 17 00:00:00 2001 From: David Stevens Date: Tue, 14 Dec 2010 08:42:16 +0000 Subject: bridge: fix IPv6 queries for bridge multicast snooping [ Upstream commit 76d661586c8131453ba75a2e027c1f21511a893a] This patch fixes a missing ntohs() for bridge IPv6 multicast snooping. Signed-off-by: David L Stevens Acked-by: Herbert Xu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/bridge/br_multicast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 27ae946363f1..5a9bcfe981c8 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -437,7 +437,7 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, ip6h = ipv6_hdr(skb); *(__force __be32 *)ip6h = htonl(0x60000000); - ip6h->payload_len = 8 + sizeof(*mldq); + ip6h->payload_len = htons(8 + sizeof(*mldq)); ip6h->nexthdr = IPPROTO_HOPOPTS; ip6h->hop_limit = 1; ipv6_addr_set(&ip6h->saddr, 0, 0, 0, 0); -- cgit v1.2.3 From 9b8a00c1f467735fbead2228f331a1182c9bb643 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 3 Nov 2010 13:31:05 +0000 Subject: cls_cgroup: Fix crash on module unload [ Upstream commit c00b2c9e79466d61979cd21af526cc6d5d0ee04f ] Somewhere along the lines net_cls_subsys_id became a macro when cls_cgroup is built as a module. Not only did it make cls_cgroup completely useless, it also causes it to crash on module unload. This patch fixes this by removing that macro. Thanks to Eric Dumazet for diagnosing this problem. Reported-by: Randy Dunlap Signed-off-by: Herbert Xu Signed-off-by: Andi Kleen Reviewed-by: Li Zefan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/cls_cgroup.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c index 78ef2c5e130b..08be223fb3dc 100644 --- a/net/sched/cls_cgroup.c +++ b/net/sched/cls_cgroup.c @@ -34,8 +34,6 @@ struct cgroup_subsys net_cls_subsys = { .populate = cgrp_populate, #ifdef CONFIG_NET_CLS_CGROUP .subsys_id = net_cls_subsys_id, -#else -#define net_cls_subsys_id net_cls_subsys.subsys_id #endif .module = THIS_MODULE, }; -- cgit v1.2.3 From 10cac669d7b9bad2207c2d63619fb265f8cb6486 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 6 Dec 2010 09:29:43 -0800 Subject: filter: fix sk_filter rcu handling [ Upstream commit 46bcf14f44d8f31ecfdc8b6708ec15a3b33316d9 ] Pavel Emelyanov tried to fix a race between sk_filter_(de|at)tach and sk_clone() in commit 47e958eac280c263397 Problem is we can have several clones sharing a common sk_filter, and these clones might want to sk_filter_attach() their own filters at the same time, and can overwrite old_filter->rcu, corrupting RCU queues. We can not use filter->rcu without being sure no other thread could do the same thing. Switch code to a more conventional ref-counting technique : Do the atomic decrement immediately and queue one rcu call back when last reference is released. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/net/sock.h | 4 +++- net/core/filter.c | 19 ++++++------------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index e2a9f591a0e3..a4089b3500a0 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1151,6 +1151,8 @@ extern void sk_common_release(struct sock *sk); /* Initialise core socket variables */ extern void sock_init_data(struct socket *sock, struct sock *sk); +extern void sk_filter_release_rcu(struct rcu_head *rcu); + /** * sk_filter_release - release a socket filter * @fp: filter to remove @@ -1161,7 +1163,7 @@ extern void sock_init_data(struct socket *sock, struct sock *sk); static inline void sk_filter_release(struct sk_filter *fp) { if (atomic_dec_and_test(&fp->refcnt)) - kfree(fp); + call_rcu_bh(&fp->rcu, sk_filter_release_rcu); } static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp) diff --git a/net/core/filter.c b/net/core/filter.c index f68e49774829..71a433cdf7d3 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -589,23 +589,16 @@ int sk_chk_filter(struct sock_filter *filter, int flen) EXPORT_SYMBOL(sk_chk_filter); /** - * sk_filter_rcu_release: Release a socket filter by rcu_head + * sk_filter_release_rcu - Release a socket filter by rcu_head * @rcu: rcu_head that contains the sk_filter to free */ -static void sk_filter_rcu_release(struct rcu_head *rcu) +void sk_filter_release_rcu(struct rcu_head *rcu) { struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu); - sk_filter_release(fp); -} - -static void sk_filter_delayed_uncharge(struct sock *sk, struct sk_filter *fp) -{ - unsigned int size = sk_filter_len(fp); - - atomic_sub(size, &sk->sk_omem_alloc); - call_rcu_bh(&fp->rcu, sk_filter_rcu_release); + kfree(fp); } +EXPORT_SYMBOL(sk_filter_release_rcu); /** * sk_attach_filter - attach a socket filter @@ -650,7 +643,7 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) rcu_read_unlock_bh(); if (old_fp) - sk_filter_delayed_uncharge(sk, old_fp); + sk_filter_uncharge(sk, old_fp); return 0; } EXPORT_SYMBOL_GPL(sk_attach_filter); @@ -664,7 +657,7 @@ int sk_detach_filter(struct sock *sk) filter = rcu_dereference_bh(sk->sk_filter); if (filter) { rcu_assign_pointer(sk->sk_filter, NULL); - sk_filter_delayed_uncharge(sk, filter); + sk_filter_uncharge(sk, filter); ret = 0; } rcu_read_unlock_bh(); -- cgit v1.2.3 From 2a0e5f9e12c4a9ab6ff63b2b6991232a4cb5a910 Mon Sep 17 00:00:00 2001 From: Nelson Elhage Date: Wed, 8 Dec 2010 10:13:55 -0800 Subject: econet: Do the correct cleanup after an unprivileged SIOCSIFADDR. [ Upstream commit 0c62fc6dd02c8d793c75ae76a9b6881fc36388ad] We need to drop the mutex and do a dev_put, so set an error code and break like the other paths, instead of returning directly. Signed-off-by: Nelson Elhage Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/econet/af_econet.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 2e41c761f414..e40e6b023500 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -661,8 +661,10 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg) err = 0; switch (cmd) { case SIOCSIFADDR: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; + if (!capable(CAP_NET_ADMIN)) { + err = -EPERM; + break; + } edev = dev->ec_ptr; if (edev == NULL) { -- cgit v1.2.3 From f59cbe486092c277cb7c00f048ed6701ebf6cdfa Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 8 Dec 2010 18:42:23 -0800 Subject: econet: Fix crash in aun_incoming(). [ Upstream commit 4e085e76cbe558b79b54cbab772f61185879bc64 ] Unconditional use of skb->dev won't work here, try to fetch the econet device via skb_dst()->dev instead. Suggested by Eric Dumazet. Reported-by: Nelson Elhage Tested-by: Nelson Elhage Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/econet/af_econet.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index e40e6b023500..c8d356c0f815 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -849,7 +849,11 @@ static void aun_incoming(struct sk_buff *skb, struct aunhdr *ah, size_t len) unsigned char stn = ntohl(ip->saddr) & 0xff; struct sock *sk; struct sk_buff *newskb; - struct ec_device *edev = skb->dev->ec_ptr; + struct dst_entry *dst = skb_dst(skb); + struct ec_device *edev = NULL; + + if (dst) + edev = dst->dev->ec_ptr; if (! edev) goto bad; -- cgit v1.2.3 From 9cd02000aea2084bbd44091f10877a3d921291d0 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Sat, 4 Dec 2010 14:09:08 +0000 Subject: ifb: goto resched directly if error happens and dp->tq isn't empty [ Upstream commit 75c1c82566f23dd539fb7ccbf57a1caa7ba82628 ] If we break the loop when there are still skbs in tq and no skb in rq, the skbs will be left in txq until new skbs are enqueued into rq. In rare cases, no new skb is queued, then these skbs will stay in rq forever. After this patch, if tq isn't empty when we break the loop, we goto resched directly. Signed-off-by: Changli Gao Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/ifb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index ab9f675c5b8b..fe337bd121aa 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -104,6 +104,8 @@ static void ri_tasklet(unsigned long dev) rcu_read_unlock(); dev_kfree_skb(skb); stats->tx_dropped++; + if (skb_queue_len(&dp->tq) != 0) + goto resched; break; } rcu_read_unlock(); -- cgit v1.2.3 From 41075cd5d8e431ad7f8eb4d57f851a7ad8fadc77 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Mon, 6 Dec 2010 02:39:12 +0000 Subject: l2tp: Fix modalias of l2tp_ip [ Upstream commit e8d34a884e4ff118920bb57664def8a73b1b784f] Using the SOCK_DGRAM enum results in "net-pf-2-proto-SOCK_DGRAM-type-115", so use the numeric value like it is done in net/dccp. Signed-off-by: Michal Marek Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/l2tp/l2tp_ip.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 0852512d392c..362e3c605997 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -676,4 +676,8 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("James Chapman "); MODULE_DESCRIPTION("L2TP over IP"); MODULE_VERSION("1.0"); -MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, SOCK_DGRAM, IPPROTO_L2TP); + +/* Use the value of SOCK_DGRAM (2) directory, because __stringify does't like + * enums + */ +MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 2, IPPROTO_L2TP); -- cgit v1.2.3 From 0ead25e6311a5b894daf6dae9a9734a3262f8f89 Mon Sep 17 00:00:00 2001 From: Apollon Oikonomopoulos Date: Tue, 7 Dec 2010 09:43:30 +0000 Subject: x25: decrement netdev reference counts on unload [ Upstream commit 171995e5d82dcc92bea37a7d2a2ecc21068a0f19] x25 does not decrement the network device reference counts on module unload. Thus unregistering any pre-existing interface after unloading the x25 module hangs and results in unregister_netdevice: waiting for tap0 to become free. Usage count = 1 This patch decrements the reference counts of all interfaces in x25_link_free, the way it is already done in x25_link_device_down for NETDEV_DOWN events. Signed-off-by: Apollon Oikonomopoulos Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/x25/x25_link.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c index 73e7b954ad28..b25c6463c3e9 100644 --- a/net/x25/x25_link.c +++ b/net/x25/x25_link.c @@ -394,6 +394,7 @@ void __exit x25_link_free(void) list_for_each_safe(entry, tmp, &x25_neigh_list) { nb = list_entry(entry, struct x25_neigh, node); __x25_remove_neigh(nb); + dev_put(nb->dev); } write_unlock_bh(&x25_neigh_list_lock); } -- cgit v1.2.3 From 0480c8a2bbec4fbc07c87cf035b0a55c20e97911 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 17 Dec 2010 10:16:23 -0800 Subject: tehuti: Firmware filename is tehuti/bdx.bin [ Upstream commit 46814e08d80f87449b5adb3d549a3cae6f9f8148 ] My conversion of tehuti to use request_firmware() was confused about the filename of the firmware blob. Change the driver to match the blob. Signed-off-by: Ben Hutchings Signed-off-by: Andy Gospodarek Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/tehuti.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 737df6032bbc..2ce585a511d9 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -324,7 +324,7 @@ static int bdx_fw_load(struct bdx_priv *priv) ENTER; master = READ_REG(priv, regINIT_SEMAPHORE); if (!READ_REG(priv, regINIT_STATUS) && master) { - rc = request_firmware(&fw, "tehuti/firmware.bin", &priv->pdev->dev); + rc = request_firmware(&fw, "tehuti/bdx.bin", &priv->pdev->dev); if (rc) goto out; bdx_tx_push_desc_safe(priv, (char *)fw->data, fw->size); @@ -2516,4 +2516,4 @@ module_exit(bdx_module_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(BDX_DRV_DESC); -MODULE_FIRMWARE("tehuti/firmware.bin"); +MODULE_FIRMWARE("tehuti/bdx.bin"); -- cgit v1.2.3 From 44a913f55f16aa0495a378f62252512cf3ad4b29 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 9 Nov 2010 11:46:33 -0800 Subject: net/dst: dst_dev_event() called after other notifiers [ Upstream commit 332dd96f7ac15e937088fe11f15cfe0210e8edd1 ] Followup of commit ef885afbf8a37689 (net: use rcu_barrier() in rollback_registered_many) dst_dev_event() scans a garbage dst list that might be feeded by various network notifiers at device dismantle time. Its important to call dst_dev_event() after other notifiers, or we might enter the infamous msleep(250) in netdev_wait_allrefs(), and wait one second before calling again call_netdevice_notifiers(NETDEV_UNREGISTER, dev) to properly remove last device references. Use priority -10 to let dst_dev_notifier be called after other network notifiers (they have the default 0 priority) Reported-by: Ben Greear Reported-by: Nicolas Dichtel Reported-by: Octavian Purdila Reported-by: Benjamin LaHaise Tested-by: Ben Greear Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/core/dst.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/dst.c b/net/core/dst.c index 9920722cc82b..1ebf5e052f61 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -343,6 +343,7 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, static struct notifier_block dst_dev_notifier = { .notifier_call = dst_dev_event, + .priority = -10, /* must be called after other network notifiers */ }; void __init dst_init(void) -- cgit v1.2.3 From 64c80cfe40b35c06a7cbf2806fcc2c14460405ab Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Mon, 8 Nov 2010 11:58:45 +0000 Subject: net: Fix header size check for GSO case in recvmsg (af_packet) [ Upstream commit 1f18b7176e2e41fada24584ce3c80e9abfaca52b] Parameter 'len' is size_t type so it will never get negative. Signed-off-by: Mariusz Kozlowski Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/packet/af_packet.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 2078a277e06b..e670cb211491 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1595,9 +1595,11 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, err = -EINVAL; vnet_hdr_len = sizeof(vnet_hdr); - if ((len -= vnet_hdr_len) < 0) + if (len < vnet_hdr_len) goto out_free; + len -= vnet_hdr_len; + if (skb_is_gso(skb)) { struct skb_shared_info *sinfo = skb_shinfo(skb); -- cgit v1.2.3 From d3c6045fee29a799083d3431da555053e3140eaf Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Wed, 10 Nov 2010 12:09:10 -0800 Subject: net: packet: fix information leak to userland [ Upstream commit 67286640f638f5ad41a946b9a3dc75327950248f ] packet_getname_spkt() doesn't initialize all members of sa_data field of sockaddr struct if strlen(dev->name) < 13. This structure is then copied to userland. It leads to leaking of contents of kernel stack memory. We have to fully fill sa_data with strncpy() instead of strlcpy(). The same with packet_getname(): it doesn't initialize sll_pkttype field of sockaddr_ll. Set it to zero. Signed-off-by: Vasiliy Kulikov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/packet/af_packet.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index e670cb211491..2f68bbdd9f50 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1706,7 +1706,7 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr, rcu_read_lock(); dev = dev_get_by_index_rcu(sock_net(sk), pkt_sk(sk)->ifindex); if (dev) - strlcpy(uaddr->sa_data, dev->name, 15); + strncpy(uaddr->sa_data, dev->name, 14); else memset(uaddr->sa_data, 0, 14); rcu_read_unlock(); @@ -1729,6 +1729,7 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr, sll->sll_family = AF_PACKET; sll->sll_ifindex = po->ifindex; sll->sll_protocol = po->num; + sll->sll_pkttype = 0; rcu_read_lock(); dev = dev_get_by_index_rcu(sock_net(sk), po->ifindex); if (dev) { -- cgit v1.2.3 From 53479596917f7de21c96b1af971370868129c8b2 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Sat, 23 Oct 2010 01:36:40 -0400 Subject: ACPICA: Fix Scope() op in module level code commit 8df3fc981dc12d9fdcaef4100a2193b605024d7a upstream. Some Panasonic Toughbooks create nodes in module level code. Module level code is the executable AML code outside of control method, for example, below AML code creates a node \_SB.PCI0.GFX0.DD02.CUBL If (\_OSI ("Windows 2006")) { Scope (\_SB.PCI0.GFX0.DD02) { Name (CUBL, Ones) ... } } Scope() op does not actually create a new object, it refers to an existing object(\_SB.PCI0.GFX0.DD02 in above example). However, for Scope(), we want to indeed open a new scope, so the child nodes(CUBL in above example) can be created correctly under it. https://bugzilla.kernel.org/show_bug.cgi?id=19462 Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/acpi/acpica/dswexec.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c index d555b374e314..6b0b5d08d97a 100644 --- a/drivers/acpi/acpica/dswexec.c +++ b/drivers/acpi/acpica/dswexec.c @@ -300,10 +300,25 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, * we must enter this object into the namespace. The created * object is temporary and will be deleted upon completion of * the execution of this method. + * + * Note 10/2010: Except for the Scope() op. This opcode does + * not actually create a new object, it refers to an existing + * object. However, for Scope(), we want to indeed open a + * new scope. */ - status = acpi_ds_load2_begin_op(walk_state, NULL); + if (op->common.aml_opcode != AML_SCOPE_OP) { + status = + acpi_ds_load2_begin_op(walk_state, NULL); + } else { + status = + acpi_ds_scope_stack_push(op->named.node, + op->named.node-> + type, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } } - break; case AML_CLASS_EXECUTE: -- cgit v1.2.3 From 89c24ec0eee40272f0387eeb6a6cc31e6bbc1544 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 16 Nov 2010 18:40:52 -0500 Subject: nouveau: Acknowledge HPD irq in handler, not bottom half commit ab838338a2a9e0cb8346eb0cab9977be13e8dce5 upstream. The old code generated an interrupt storm bad enough to completely take down my system. Signed-off-by: Andy Lutomirski Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/nouveau/nouveau_drv.h | 6 ++++++ drivers/gpu/drm/nouveau/nouveau_irq.c | 1 + drivers/gpu/drm/nouveau/nv50_display.c | 35 +++++++++++++++++++++++++--------- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index c69719106489..0e24c8038464 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -522,6 +522,12 @@ struct drm_nouveau_private { struct work_struct irq_work; struct work_struct hpd_work; + struct { + spinlock_t lock; + uint32_t hpd0_bits; + uint32_t hpd1_bits; + } hpd_state; + struct list_head vbl_waiting; struct { diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 53360f156063..4a3e3661bb6e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -52,6 +52,7 @@ nouveau_irq_preinstall(struct drm_device *dev) if (dev_priv->card_type == NV_50) { INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh); + spin_lock_init(&dev_priv->hpd_state.lock); INIT_LIST_HEAD(&dev_priv->vbl_waiting); } } diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 580a5d10be93..1a4408bc1dff 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -930,11 +930,18 @@ nv50_display_irq_hotplug_bh(struct work_struct *work) struct drm_connector *connector; const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; uint32_t unplug_mask, plug_mask, change_mask; - uint32_t hpd0, hpd1 = 0; + uint32_t hpd0, hpd1; - hpd0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050); + spin_lock_irq(&dev_priv->hpd_state.lock); + hpd0 = dev_priv->hpd_state.hpd0_bits; + dev_priv->hpd_state.hpd0_bits = 0; + hpd1 = dev_priv->hpd_state.hpd1_bits; + dev_priv->hpd_state.hpd1_bits = 0; + spin_unlock_irq(&dev_priv->hpd_state.lock); + + hpd0 &= nv_rd32(dev, 0xe050); if (dev_priv->chipset >= 0x90) - hpd1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070); + hpd1 &= nv_rd32(dev, 0xe070); plug_mask = (hpd0 & 0x0000ffff) | (hpd1 << 16); unplug_mask = (hpd0 >> 16) | (hpd1 & 0xffff0000); @@ -976,10 +983,6 @@ nv50_display_irq_hotplug_bh(struct work_struct *work) helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF); } - nv_wr32(dev, 0xe054, nv_rd32(dev, 0xe054)); - if (dev_priv->chipset >= 0x90) - nv_wr32(dev, 0xe074, nv_rd32(dev, 0xe074)); - drm_helper_hpd_irq_event(dev); } @@ -990,8 +993,22 @@ nv50_display_irq_handler(struct drm_device *dev) uint32_t delayed = 0; if (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) { - if (!work_pending(&dev_priv->hpd_work)) - queue_work(dev_priv->wq, &dev_priv->hpd_work); + uint32_t hpd0_bits, hpd1_bits = 0; + + hpd0_bits = nv_rd32(dev, 0xe054); + nv_wr32(dev, 0xe054, hpd0_bits); + + if (dev_priv->chipset >= 0x90) { + hpd1_bits = nv_rd32(dev, 0xe074); + nv_wr32(dev, 0xe074, hpd1_bits); + } + + spin_lock(&dev_priv->hpd_state.lock); + dev_priv->hpd_state.hpd0_bits |= hpd0_bits; + dev_priv->hpd_state.hpd1_bits |= hpd1_bits; + spin_unlock(&dev_priv->hpd_state.lock); + + queue_work(dev_priv->wq, &dev_priv->hpd_work); } while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { -- cgit v1.2.3 From 78dd4b02b5d68c4d64557152a35941150f90ff82 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 26 Nov 2010 13:42:47 +0100 Subject: printk: Fix wake_up_klogd() vs cpu hotplug commit 49f4138346b3cec2706adff02658fe27ceb1e46f upstream. wake_up_klogd() may get called from preemptible context but uses __raw_get_cpu_var() to write to a per cpu variable. If it gets preempted between getting the address and writing to it, the cpu in question could be offline if the process gets scheduled back and hence writes to the per cpu data of an offline cpu. This buggy behaviour was introduced with fa33507a "printk: robustify printk, fix #2" which was supposed to fix a "using smp_processor_id() in preemptible" warning. Let's use this_cpu_write() instead which disables preemption and makes sure that the outlined scenario cannot happen. Signed-off-by: Heiko Carstens Acked-by: Eric Dumazet Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <20101126124247.GC7023@osiris.boeblingen.de.ibm.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/printk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/printk.c b/kernel/printk.c index ea64cb5dd0ba..b7b7f90aad6e 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -1042,7 +1042,7 @@ int printk_needs_cpu(int cpu) void wake_up_klogd(void) { if (waitqueue_active(&log_wait)) - __raw_get_cpu_var(printk_pending) = 1; + this_cpu_write(printk_pending, 1); } /** -- cgit v1.2.3 From 92bc7287b38e4eb45ff34b1cd1b543da9d1e71bd Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 8 Dec 2010 12:39:12 -0800 Subject: xen: Provide a variant of __RING_SIZE() that is an integer constant expression commit 667c78afaec0ac500908e191e8f236e9578d7b1f upstream. Without this, gcc 4.5 won't compile xen-netfront and xen-blkfront, where this is being used to specify array sizes. Signed-off-by: Jan Beulich Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Andi Kleen Cc: Jens Axboe Cc: David Miller Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/block/xen-blkfront.c | 2 +- drivers/net/xen-netfront.c | 4 ++-- include/xen/interface/io/ring.h | 11 +++++++++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 82ed403147c0..d95f0b4864eb 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -69,7 +69,7 @@ struct blk_shadow { static const struct block_device_operations xlvbd_block_fops; -#define BLK_RING_SIZE __RING_SIZE((struct blkif_sring *)0, PAGE_SIZE) +#define BLK_RING_SIZE __CONST_RING_SIZE(blkif, PAGE_SIZE) /* * We have one of these per vbd, whether ide, scsi or 'other'. They diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index b50fedcef8ac..42dad59cadb0 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -66,8 +66,8 @@ struct netfront_cb { #define GRANT_INVALID_REF 0 -#define NET_TX_RING_SIZE __RING_SIZE((struct xen_netif_tx_sring *)0, PAGE_SIZE) -#define NET_RX_RING_SIZE __RING_SIZE((struct xen_netif_rx_sring *)0, PAGE_SIZE) +#define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE) +#define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE) #define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256) struct netfront_info { diff --git a/include/xen/interface/io/ring.h b/include/xen/interface/io/ring.h index e8cbf431c8cc..75271b9a8f61 100644 --- a/include/xen/interface/io/ring.h +++ b/include/xen/interface/io/ring.h @@ -24,8 +24,15 @@ typedef unsigned int RING_IDX; * A ring contains as many entries as will fit, rounded down to the nearest * power of two (so we can mask with (size-1) to loop around). */ -#define __RING_SIZE(_s, _sz) \ - (__RD32(((_sz) - (long)&(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0]))) +#define __CONST_RING_SIZE(_s, _sz) \ + (__RD32(((_sz) - offsetof(struct _s##_sring, ring)) / \ + sizeof(((struct _s##_sring *)0)->ring[0]))) + +/* + * The same for passing in an actual pointer instead of a name tag. + */ +#define __RING_SIZE(_s, _sz) \ + (__RD32(((_sz) - (long)&(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0]))) /* * Macros to make the correct C datatypes for a new kind of ring. -- cgit v1.2.3 From 8800f8aba29a1f6d9c0cb9612926802b03516b7f Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 30 Nov 2010 19:48:45 +0100 Subject: sched: Cure more NO_HZ load average woes commit 0f004f5a696a9434b7214d0d3cbd0525ee77d428 upstream. There's a long-running regression that proved difficult to fix and which is hitting certain people and is rather annoying in its effects. Damien reported that after 74f5187ac8 (sched: Cure load average vs NO_HZ woes) his load average is unnaturally high, he also noted that even with that patch reverted the load avgerage numbers are not correct. The problem is that the previous patch only solved half the NO_HZ problem, it addressed the part of going into NO_HZ mode, not of comming out of NO_HZ mode. This patch implements that missing half. When comming out of NO_HZ mode there are two important things to take care of: - Folding the pending idle delta into the global active count. - Correctly aging the averages for the idle-duration. So with this patch the NO_HZ interaction should be complete and behaviour between CONFIG_NO_HZ=[yn] should be equivalent. Furthermore, this patch slightly changes the load average computation by adding a rounding term to the fixed point multiplication. Reported-by: Damien Wyart Reported-by: Tim McGrath Tested-by: Damien Wyart Tested-by: Orion Poplawski Tested-by: Kyle McMartin Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen Cc: Chase Douglas LKML-Reference: <1291129145.32004.874.camel@laptop> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- include/linux/sched.h | 2 +- kernel/sched.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++---- kernel/timer.c | 2 +- 3 files changed, 141 insertions(+), 13 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 5ee397ee3bca..1272de4e7b3f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -143,7 +143,7 @@ extern unsigned long nr_iowait_cpu(int cpu); extern unsigned long this_cpu_load(void); -extern void calc_global_load(void); +extern void calc_global_load(unsigned long ticks); extern unsigned long get_parent_ip(unsigned long addr); diff --git a/kernel/sched.c b/kernel/sched.c index 837f480d842c..4c89e4feff60 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2890,6 +2890,15 @@ static long calc_load_fold_active(struct rq *this_rq) return delta; } +static unsigned long +calc_load(unsigned long load, unsigned long exp, unsigned long active) +{ + load *= exp; + load += active * (FIXED_1 - exp); + load += 1UL << (FSHIFT - 1); + return load >> FSHIFT; +} + #ifdef CONFIG_NO_HZ /* * For NO_HZ we delay the active fold to the next LOAD_FREQ update. @@ -2919,6 +2928,128 @@ static long calc_load_fold_idle(void) return delta; } + +/** + * fixed_power_int - compute: x^n, in O(log n) time + * + * @x: base of the power + * @frac_bits: fractional bits of @x + * @n: power to raise @x to. + * + * By exploiting the relation between the definition of the natural power + * function: x^n := x*x*...*x (x multiplied by itself for n times), and + * the binary encoding of numbers used by computers: n := \Sum n_i * 2^i, + * (where: n_i \elem {0, 1}, the binary vector representing n), + * we find: x^n := x^(\Sum n_i * 2^i) := \Prod x^(n_i * 2^i), which is + * of course trivially computable in O(log_2 n), the length of our binary + * vector. + */ +static unsigned long +fixed_power_int(unsigned long x, unsigned int frac_bits, unsigned int n) +{ + unsigned long result = 1UL << frac_bits; + + if (n) for (;;) { + if (n & 1) { + result *= x; + result += 1UL << (frac_bits - 1); + result >>= frac_bits; + } + n >>= 1; + if (!n) + break; + x *= x; + x += 1UL << (frac_bits - 1); + x >>= frac_bits; + } + + return result; +} + +/* + * a1 = a0 * e + a * (1 - e) + * + * a2 = a1 * e + a * (1 - e) + * = (a0 * e + a * (1 - e)) * e + a * (1 - e) + * = a0 * e^2 + a * (1 - e) * (1 + e) + * + * a3 = a2 * e + a * (1 - e) + * = (a0 * e^2 + a * (1 - e) * (1 + e)) * e + a * (1 - e) + * = a0 * e^3 + a * (1 - e) * (1 + e + e^2) + * + * ... + * + * an = a0 * e^n + a * (1 - e) * (1 + e + ... + e^n-1) [1] + * = a0 * e^n + a * (1 - e) * (1 - e^n)/(1 - e) + * = a0 * e^n + a * (1 - e^n) + * + * [1] application of the geometric series: + * + * n 1 - x^(n+1) + * S_n := \Sum x^i = ------------- + * i=0 1 - x + */ +static unsigned long +calc_load_n(unsigned long load, unsigned long exp, + unsigned long active, unsigned int n) +{ + + return calc_load(load, fixed_power_int(exp, FSHIFT, n), active); +} + +/* + * NO_HZ can leave us missing all per-cpu ticks calling + * calc_load_account_active(), but since an idle CPU folds its delta into + * calc_load_tasks_idle per calc_load_account_idle(), all we need to do is fold + * in the pending idle delta if our idle period crossed a load cycle boundary. + * + * Once we've updated the global active value, we need to apply the exponential + * weights adjusted to the number of cycles missed. + */ +static void calc_global_nohz(unsigned long ticks) +{ + long delta, active, n; + + if (time_before(jiffies, calc_load_update)) + return; + + /* + * If we crossed a calc_load_update boundary, make sure to fold + * any pending idle changes, the respective CPUs might have + * missed the tick driven calc_load_account_active() update + * due to NO_HZ. + */ + delta = calc_load_fold_idle(); + if (delta) + atomic_long_add(delta, &calc_load_tasks); + + /* + * If we were idle for multiple load cycles, apply them. + */ + if (ticks >= LOAD_FREQ) { + n = ticks / LOAD_FREQ; + + active = atomic_long_read(&calc_load_tasks); + active = active > 0 ? active * FIXED_1 : 0; + + avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n); + avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n); + avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n); + + calc_load_update += n * LOAD_FREQ; + } + + /* + * Its possible the remainder of the above division also crosses + * a LOAD_FREQ period, the regular check in calc_global_load() + * which comes after this will take care of that. + * + * Consider us being 11 ticks before a cycle completion, and us + * sleeping for 4*LOAD_FREQ + 22 ticks, then the above code will + * age us 4 cycles, and the test in calc_global_load() will + * pick up the final one. + */ +} #else static void calc_load_account_idle(struct rq *this_rq) { @@ -2928,6 +3059,10 @@ static inline long calc_load_fold_idle(void) { return 0; } + +static void calc_global_nohz(unsigned long ticks) +{ +} #endif /** @@ -2945,24 +3080,17 @@ void get_avenrun(unsigned long *loads, unsigned long offset, int shift) loads[2] = (avenrun[2] + offset) << shift; } -static unsigned long -calc_load(unsigned long load, unsigned long exp, unsigned long active) -{ - load *= exp; - load += active * (FIXED_1 - exp); - return load >> FSHIFT; -} - /* * calc_load - update the avenrun load estimates 10 ticks after the * CPUs have updated calc_load_tasks. */ -void calc_global_load(void) +void calc_global_load(unsigned long ticks) { - unsigned long upd = calc_load_update + 10; long active; - if (time_before(jiffies, upd)) + calc_global_nohz(ticks); + + if (time_before(jiffies, calc_load_update + 10)) return; active = atomic_long_read(&calc_load_tasks); diff --git a/kernel/timer.c b/kernel/timer.c index 14f13e9c8dc7..f7dec455d826 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1308,7 +1308,7 @@ void do_timer(unsigned long ticks) { jiffies_64 += ticks; update_wall_time(); - calc_global_load(); + calc_global_load(ticks); } #ifdef __ARCH_WANT_SYS_ALARM -- cgit v1.2.3 From 998adceb18cdd62b03d267219eb1e967332a9663 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Thu, 9 Dec 2010 17:07:54 -0500 Subject: ACPI: EC: Add another dmi match entry for MSI hardware commit a5dc4f898c2a0f66e2cefada6c687db82ba2fcbc upstream. http://bugzilla.kernel.org/show_bug.cgi?id=15418 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/acpi/ec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 5f2027d782e8..2d4b732fbbf5 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1006,6 +1006,9 @@ static struct dmi_system_id __initdata ec_dmi_table[] = { ec_flag_msi, "MSI hardware", { DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star")}, NULL}, { + ec_flag_msi, "MSI hardware", { + DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR")}, NULL}, + { ec_validate_ecdt, "ASUS hardware", { DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL}, {}, -- cgit v1.2.3 From 6559ff535c6a7d61eb22295ddf390ac917f46275 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 16 Dec 2010 17:11:58 +0100 Subject: PM / Runtime: Fix pm_runtime_suspended() commit f08f5a0add20834d3f3d876dfe08005a5df656db upstream. There are some situations (e.g. in __pm_generic_call()), where pm_runtime_suspended() is used to decide whether or not to execute a device's (system) ->suspend() callback. The callback is not executed if pm_runtime_suspended() returns true, but it does so for devices that don't even support runtime PM, because the power.disable_depth device field is ignored by it. This leads to problems (i.e. devices are not suspened when they should), so rework pm_runtime_suspended() so that it returns false if the device's power.disable_depth field is different from zero. Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- Documentation/power/runtime_pm.txt | 4 ++-- include/linux/pm_runtime.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 55b859b3bc72..506d9d916e41 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -336,8 +336,8 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: zero) bool pm_runtime_suspended(struct device *dev); - - return true if the device's runtime PM status is 'suspended', or false - otherwise + - return true if the device's runtime PM status is 'suspended' and its + 'power.disable_depth' field is equal to zero, or false otherwise void pm_runtime_allow(struct device *dev); - set the power.runtime_auto flag for the device and decrease its usage diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index 6e81888c6222..5ea4b1582b07 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -67,7 +67,8 @@ static inline void device_set_run_wake(struct device *dev, bool enable) static inline bool pm_runtime_suspended(struct device *dev) { - return dev->power.runtime_status == RPM_SUSPENDED; + return dev->power.runtime_status == RPM_SUSPENDED + && !dev->power.disable_depth; } #else /* !CONFIG_PM_RUNTIME */ -- cgit v1.2.3 From a1a584f5c28939e5c11d062b233599034748d6dd Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 23 Nov 2010 18:18:37 -0500 Subject: inotify: stop kernel memory leak on file creation failure commit a2ae4cc9a16e211c8a128ba10d22a85431f093ab upstream. If inotify_init is unable to allocate a new file for the new inotify group we leak the new group. This patch drops the reference on the group on file allocation failure. Reported-by: Vegard Nossum Signed-off-by: Eric Paris Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/notify/inotify/inotify_user.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 0c6bbc031f15..72f882552608 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -674,6 +674,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags) if (ret >= 0) return ret; + fsnotify_put_group(group); atomic_dec(&user->inotify_devs); out_free_uid: free_uid(user); -- cgit v1.2.3 From c0be80088ed2d65565fa02732030a7bfc9a7a0c6 Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Sun, 5 Dec 2010 15:43:55 +0000 Subject: orinoco: fix TKIP countermeasure behaviour commit 0a54917c3fc295cb61f3fb52373c173fd3b69f48 upstream. Enable the port when disabling countermeasures, and disable it on enabling countermeasures. This bug causes the response of the system to certain attacks to be ineffective. It also prevents wpa_supplicant from getting scan results, as wpa_supplicant disables countermeasures on startup - preventing the hardware from scanning. wpa_supplicant works with ap_mode=2 despite this bug because the commit handler re-enables the port. The log tends to look like: State: DISCONNECTED -> SCANNING Starting AP scan for wildcard SSID Scan requested (ret=0) - scan timeout 5 seconds EAPOL: disable timer tick EAPOL: Supplicant port status: Unauthorized Scan timeout - try to get results Failed to get scan results Failed to get scan results - try scanning again Setting scan request: 1 sec 0 usec Starting AP scan for wildcard SSID Scan requested (ret=-1) - scan timeout 5 seconds Failed to initiate AP scan. Reported by: Giacomo Comes Signed-off by: David Kilroy Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/orinoco/wext.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index 5775124e2aee..77b2d7b63beb 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c @@ -904,10 +904,10 @@ static int orinoco_ioctl_set_auth(struct net_device *dev, */ if (param->value) { priv->tkip_cm_active = 1; - ret = hermes_enable_port(hw, 0); + ret = hermes_disable_port(hw, 0); } else { priv->tkip_cm_active = 0; - ret = hermes_disable_port(hw, 0); + ret = hermes_enable_port(hw, 0); } break; -- cgit v1.2.3 From 6660a58806566b5b452b8b6458be90526fbec054 Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Sun, 5 Dec 2010 15:45:58 +0000 Subject: orinoco: clear countermeasure setting on commit commit ba34fcee476d11e7c9df95932787a22a96ff6e68 upstream. ... and interface up. In these situations, you are usually trying to connect to a new AP, so keeping TKIP countermeasures active is confusing. This is already how the driver behaves (inadvertently). However, querying SIOCGIWAUTH may tell userspace that countermeasures are active when they aren't. Clear the setting so that the reporting matches what the driver has done.. Signed-off by: David Kilroy Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/orinoco/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index ca71f08709bc..87c7acafe2c4 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -1813,6 +1813,12 @@ static int __orinoco_commit(struct orinoco_private *priv) struct net_device *dev = priv->ndev; int err = 0; + /* If we've called commit, we are reconfiguring or bringing the + * interface up. Maintaining countermeasures across this would + * be confusing, so note that we've disabled them. The port will + * be enabled later in orinoco_commit or __orinoco_up. */ + priv->tkip_cm_active = 0; + err = orinoco_hw_program_rids(priv); /* FIXME: what about netif_tx_lock */ -- cgit v1.2.3 From 5ed561673a5aa6c8f5a65b958dd0e0b2e0bd3bda Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Thu, 16 Dec 2010 21:29:37 +0100 Subject: x86, amd: Fix panic on AMD CPU family 0x15 [The mainline kernel doesn't have this problem. Commit "(23588c3) x86, amd: Add support for CPUID topology extension of AMD CPUs" removed the family check. But 2.6.32.y needs to be fixed.] This CPU family check is not required -- existence of the NodeId MSR is indicated by a CPUID feature flag which is already checked in amd_fixup_dcm() -- and it needlessly prevents amd_fixup_dcm() to be called for newer AMD CPUs. In worst case this can lead to a panic in the scheduler code for AMD family 0x15 multi-node AMD CPUs. I just have a picture of VGA console output so I can't copy-and-paste it herein, but the call stack of such a panic looked like: do_divide_error ... find_busiest_group run_rebalance_domains ... apic_timer_interrupt ... cpu_idle The mainline kernel doesn't have this problem. Commit "(23588c3) x86, amd: Add support for CPUID topology extension of AMD CPUs" removed the family check. But 2.6.32.y needs to be fixed. Signed-off-by: Andreas Herrmann Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/kernel/cpu/amd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index e485825130d2..d11629a89b03 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -305,8 +305,7 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c) /* use socket ID also for last level cache */ per_cpu(cpu_llc_id, cpu) = c->phys_proc_id; /* fixup topology information on multi-node processors */ - if ((c->x86 == 0x10) && (c->x86_model == 9)) - amd_fixup_dcm(c); + amd_fixup_dcm(c); #endif } -- cgit v1.2.3 From 1eb3d729169b026e40f0094f0d602187ebdff165 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 9 Dec 2010 16:36:28 +1100 Subject: md: fix bug with re-adding of partially recovered device. commit 1a855a0606653d2d82506281e2c686bacb4b2f45 upstream. With v0.90 metadata, a hot-spare does not become a full member of the array until recovery is complete. So if we re-add such a device to the array, we know that all of it is as up-to-date as the event count would suggest, and so it a bitmap-based recovery is possible. However with v1.x metadata, the hot-spare immediately becomes a full member of the array, but it record how much of the device has been recovered. If the array is stopped and re-assembled recovery starts from this point. When such a device is hot-added to an array we currently lose the 'how much is recovered' information and incorrectly included it as a full in-sync member (after bitmap-based fixup). This is wrong and unsafe and could corrupt data. So be more careful about setting saved_raid_disk - which is what guides the re-adding of devices back into an array. The new code matches the code in slot_store which does a similar thing, which is encouraging. This is suitable for any -stable kernel. Reported-by: "Dailey, Nate" Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/md/md.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 7de96c2c68ac..7265d117afd7 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5109,7 +5109,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) PTR_ERR(rdev)); return PTR_ERR(rdev); } - /* set save_raid_disk if appropriate */ + /* set saved_raid_disk if appropriate */ if (!mddev->persistent) { if (info->state & (1<raid_disk < mddev->raid_disks) @@ -5119,7 +5119,10 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) } else super_types[mddev->major_version]. validate_super(mddev, rdev); - rdev->saved_raid_disk = rdev->raid_disk; + if (test_bit(In_sync, &rdev->flags)) + rdev->saved_raid_disk = rdev->raid_disk; + else + rdev->saved_raid_disk = -1; clear_bit(In_sync, &rdev->flags); /* just to be sure */ if (info->state & (1< Date: Thu, 9 Dec 2010 17:02:14 +1100 Subject: md: protect against NULL reference when waiting to start a raid10. commit 589a594be1fb8815b3f18e517be696c48664f728 upstream. When we fail to start a raid10 for some reason, we call md_unregister_thread to kill the thread that was created. Unfortunately md_thread() will then make one call into the handler (raid10d) even though md_wakeup_thread has not been called. This is not safe and as md_unregister_thread is called after mddev->private has been set to NULL, it will definitely cause a NULL dereference. So fix this at both ends: - md_thread should only call the handler if THREAD_WAKEUP has been set. - raid10 should call md_unregister_thread before setting things to NULL just like all the other raid modules do. This is applicable to 2.6.35 and later. Reported-by: "Citizen" Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/md/md.c | 5 ++--- drivers/md/raid10.c | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 7265d117afd7..ef1dae2770ca 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5989,9 +5989,8 @@ static int md_thread(void * arg) || kthread_should_stop(), thread->timeout); - clear_bit(THREAD_WAKEUP, &thread->flags); - - thread->run(thread->mddev); + if (test_and_clear_bit(THREAD_WAKEUP, &thread->flags)) + thread->run(thread->mddev); } return 0; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index d1d689126346..66fe4874ffd8 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -2393,13 +2393,13 @@ static int run(mddev_t *mddev) return 0; out_free_conf: + md_unregister_thread(mddev->thread); if (conf->r10bio_pool) mempool_destroy(conf->r10bio_pool); safe_put_page(conf->tmppage); kfree(conf->mirrors); kfree(conf); mddev->private = NULL; - md_unregister_thread(mddev->thread); out: return -EIO; } -- cgit v1.2.3 From be5057e86f2813ec2a16bf0878d0d2cc6dae5e81 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 24 Nov 2010 15:13:16 -0800 Subject: tracing: Fix panic when lseek() called on "trace" opened for writing commit 364829b1263b44aa60383824e4c1289d83d78ca7 upstream. The file_ops struct for the "trace" special file defined llseek as seq_lseek(). However, if the file was opened for writing only, seq_open() was not called, and the seek would dereference a null pointer, file->private_data. This patch introduces a new wrapper for seq_lseek() which checks if the file descriptor is opened for reading first. If not, it does nothing. Signed-off-by: Slava Pestov Signed-off-by: Andi Kleen LKML-Reference: <1290640396-24179-1-git-send-email-slavapestov@google.com> Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/trace/trace.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 086d36316805..755d3ee9d453 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -2382,11 +2382,19 @@ tracing_write_stub(struct file *filp, const char __user *ubuf, return count; } +static loff_t tracing_seek(struct file *file, loff_t offset, int origin) +{ + if (file->f_mode & FMODE_READ) + return seq_lseek(file, offset, origin); + else + return 0; +} + static const struct file_operations tracing_fops = { .open = tracing_open, .read = seq_read, .write = tracing_write_stub, - .llseek = seq_lseek, + .llseek = tracing_seek, .release = tracing_release, }; -- cgit v1.2.3 From 9bc128312605cb2962c00fa63d626ebc22c8b4bc Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 13 Dec 2010 16:01:38 -0800 Subject: x86, gcc-4.6: Use gcc -m options when building vdso commit de2a8cf98ecdde25231d6c5e7901e2cffaf32af9 upstream. The vdso Makefile passes linker-style -m options not to the linker but to gcc. This happens to work with earlier gcc, but fails with gcc 4.6. Pass gcc-style -m options, instead. Note: all currently supported versions of gcc supports -m32, so there is no reason to conditionalize it any more. Reported-by: H. J. Lu Signed-off-by: H. Peter Anvin Signed-off-by: Andi Kleen LKML-Reference: Signed-off-by: Greg Kroah-Hartman --- arch/x86/vdso/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile index 6b4ffedb93c9..dd78ef687c5e 100644 --- a/arch/x86/vdso/Makefile +++ b/arch/x86/vdso/Makefile @@ -25,7 +25,7 @@ targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y) export CPPFLAGS_vdso.lds += -P -C -VDSO_LDFLAGS_vdso.lds = -m elf_x86_64 -Wl,-soname=linux-vdso.so.1 \ +VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \ -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096 $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so @@ -69,7 +69,7 @@ vdso32.so-$(VDSO32-y) += sysenter vdso32-images = $(vdso32.so-y:%=vdso32-%.so) CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds) -VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -Wl,-soname=linux-gate.so.1 +VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-soname=linux-gate.so.1 # This makes sure the $(obj) subdirectory exists even though vdso32/ # is not a kbuild sub-make subdirectory. -- cgit v1.2.3 From 7ec0309573de69959a7840e5007831625a35af87 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 30 Nov 2010 22:22:28 -0800 Subject: x86: Enable the intr-remap fault handling after local APIC setup commit 7f7fbf45c6b748074546f7f16b9488ca71de99c1 upstream. Interrupt-remapping gets enabled very early in the boot, as it determines the apic mode that the processor can use. And the current code enables the vt-d fault handling before the setup_local_APIC(). And hence the APIC LDR registers and data structure in the memory may not be initialized. So the vt-d fault handling in logical xapic/x2apic modes were broken. Fix this by enabling the vt-d fault handling in the end_local_APIC_setup() A cleaner fix of enabling fault handling while enabling intr-remapping will be addressed for v2.6.38. [ Enabling intr-remapping determines the usage of x2apic mode and the apic mode determines the fault-handling configuration. ] Signed-off-by: Kenji Kaneshige Signed-off-by: Andi Kleen LKML-Reference: <20101201062244.541996375@intel.com> Signed-off-by: Suresh Siddha Acked-by: Chris Wright Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/apic/apic.c | 8 ++++++++ arch/x86/kernel/apic/probe_64.c | 7 ------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index c07e51391a3f..6583884a83fb 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1340,6 +1340,14 @@ void __cpuinit end_local_APIC_setup(void) setup_apic_nmi_watchdog(NULL); apic_pm_activate(); + + /* + * Now that local APIC setup is completed for BP, configure the fault + * handling for interrupt remapping. + */ + if (!smp_processor_id() && intr_remapping_enabled) + enable_drhd_fault_handling(); + } #ifdef CONFIG_X86_X2APIC diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c index 83e9be4778e2..fac49a845064 100644 --- a/arch/x86/kernel/apic/probe_64.c +++ b/arch/x86/kernel/apic/probe_64.c @@ -76,13 +76,6 @@ void __init default_setup_apic_routing(void) /* need to update phys_pkg_id */ apic->phys_pkg_id = apicid_phys_pkg_id; } - - /* - * Now that apic routing model is selected, configure the - * fault handling for intr remapping. - */ - if (intr_remapping_enabled) - enable_drhd_fault_handling(); } /* Same for both flat and physical. */ -- cgit v1.2.3 From 5ed07572d5fda48533aa86ef2127bcbcda90756c Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 30 Nov 2010 22:22:29 -0800 Subject: x86, vt-d: Handle previous faults after enabling fault handling commit 7f99d946e71e71d484b7543b49e990508e70d0c0 upstream. Fault handling is getting enabled after enabling the interrupt-remapping (as the success of interrupt-remapping can affect the apic mode and hence the fault handling mode). Hence there can potentially be some faults between the window of enabling interrupt-remapping in the vt-d and the fault-handling of the vt-d units. Handle any previous faults after enabling the vt-d fault handling. For v2.6.38 cleanup, need to check if we can remove the dmar_fault() in the enable_intr_remapping() and see if we can enable fault handling along with enabling intr-remapping. Signed-off-by: Suresh Siddha Signed-off-by: Andi Kleen LKML-Reference: <20101201062244.630417138@intel.com> Acked-by: Chris Wright Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- drivers/pci/dmar.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 0a19708074c2..a286959db67e 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -1414,6 +1414,11 @@ int __init enable_drhd_fault_handling(void) (unsigned long long)drhd->reg_base_addr, ret); return -1; } + + /* + * Clear any previous faults. + */ + dmar_fault(iommu->irq, iommu); } return 0; -- cgit v1.2.3 From db8017f7d5d564075ed244ee06aad94a761c967e Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Wed, 1 Dec 2010 09:40:32 -0800 Subject: x86, vt-d: Fix the vt-d fault handling irq migration in the x2apic mode commit 086e8ced65d9bcc4a8e8f1cd39b09640f2883f90 upstream. In x2apic mode, we need to set the upper address register of the fault handling interrupt register of the vt-d hardware. Without this irq migration of the vt-d fault handling interrupt is broken. Signed-off-by: Kenji Kaneshige Signed-off-by: Andi Kleen LKML-Reference: <1291225233.2648.39.camel@sbsiddha-MOBL3> Signed-off-by: Suresh Siddha Acked-by: Chris Wright Tested-by: Takao Indoh Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/apic/io_apic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index ad1515dbc5ef..4d90327853b7 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -3626,6 +3626,7 @@ static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask) msg.data |= MSI_DATA_VECTOR(cfg->vector); msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; msg.address_lo |= MSI_ADDR_DEST_ID(dest); + msg.address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(dest); dmar_msi_write(irq, &msg); -- cgit v1.2.3 From 7be78b074a2a515de05d3eaed8885a38e3b06db1 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Mon, 6 Dec 2010 12:26:30 -0800 Subject: x86, vt-d: Quirk for masking vtd spec errors to platform error handling logic commit 254e42006c893f45bca48f313536fcba12206418 upstream. On platforms with Intel 7500 chipset, there were some reports of system hang/NMI's during kexec/kdump in the presence of interrupt-remapping enabled. During kdump, there is a window where the devices might be still using old kernel's interrupt information, while the kdump kernel is coming up. This can cause vt-d faults as the interrupt configuration from the old kernel map to null IRTE entries in the new kernel etc. (with out interrupt-remapping enabled, we still have the same issue but in this case we will see benign spurious interrupt hit the new kernel). Based on platform config settings, these platforms seem to generate NMI/SMI when a vt-d fault happens and there were reports that the resulting SMI causes the system to hang. Fix it by masking vt-d spec defined errors to platform error reporting logic. VT-d spec related errors are already handled by the VT-d OS code, so need to report the same error through other channels. Signed-off-by: Suresh Siddha Signed-off-by: Andi Kleen LKML-Reference: <1291667190.2675.8.camel@sbsiddha-MOBL3.sc.intel.com> Reported-by: Max Asbock Reported-and-tested-by: Takao Indoh Acked-by: Chris Wright Acked-by: Kenji Kaneshige Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 2a73ceb35b32..0e9acdefb13d 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2678,6 +2678,29 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_m DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); #endif /*CONFIG_MMC_RICOH_MMC*/ +#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP) +#define VTUNCERRMSK_REG 0x1ac +#define VTD_MSK_SPEC_ERRORS (1 << 31) +/* + * This is a quirk for masking vt-d spec defined errors to platform error + * handling logic. With out this, platforms using Intel 7500, 5500 chipsets + * (and the derivative chipsets like X58 etc) seem to generate NMI/SMI (based + * on the RAS config settings of the platform) when a vt-d fault happens. + * The resulting SMI caused the system to hang. + * + * VT-d spec related errors are already handled by the VT-d OS code, so no + * need to report the same error through other channels. + */ +static void vtd_mask_spec_errors(struct pci_dev *dev) +{ + u32 word; + + pci_read_config_dword(dev, VTUNCERRMSK_REG, &word); + pci_write_config_dword(dev, VTUNCERRMSK_REG, word | VTD_MSK_SPEC_ERRORS); +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, vtd_mask_spec_errors); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors); +#endif static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) -- cgit v1.2.3 From 872efb20c881ed307078621f2078b3a94527d8a1 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 23 Aug 2010 19:56:07 +0200 Subject: rt2x00: Fix max TX power settings commit 8d1331b37d5b656a7a8e561f8e9d7661dd00c910 upstream. During initialization each driver reads the default TX power for each individual channel. However mac80211 only accepts the maximum value (which is also handled as default value). As a result, the TX power of the device was being limited to the default value, which is often quite low compared to the real maximum acceptable value. This patch allows each driver to set the maximum value on a per-channel basis which is forwarded to mac80211. The default value will be preserved for now, in case we want to update mac80211 to differentiate between the maximum and default txpower. This fixes bug complaining about limited TX power values like: https://bugzilla.kernel.org/show_bug.cgi?id=16358 Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/rt2x00/rt2400pci.c | 6 ++-- drivers/net/wireless/rt2x00/rt2500pci.c | 12 ++++--- drivers/net/wireless/rt2x00/rt2500usb.c | 12 ++++--- drivers/net/wireless/rt2x00/rt2800.h | 7 ++++ drivers/net/wireless/rt2x00/rt2800lib.c | 59 +++++++++++++++++++-------------- drivers/net/wireless/rt2x00/rt2x00.h | 5 +-- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- drivers/net/wireless/rt2x00/rt61pci.c | 12 ++++--- drivers/net/wireless/rt2x00/rt73usb.c | 12 ++++--- 9 files changed, 82 insertions(+), 45 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index ad2c98af7e9d..f57f0df45a68 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1462,8 +1462,10 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->channels_info = info; tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START); - for (i = 0; i < 14; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); + for (i = 0; i < 14; i++) { + info[i].max_power = TXPOWER_FROM_DEV(MAX_TXPOWER); + info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + } return 0; } diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 41da3d218c65..fec3d9e636d1 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1780,12 +1780,16 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->channels_info = info; tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START); - for (i = 0; i < 14; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); + for (i = 0; i < 14; i++) { + info[i].max_power = MAX_TXPOWER; + info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + } if (spec->num_channels > 14) { - for (i = 14; i < spec->num_channels; i++) - info[i].tx_power1 = DEFAULT_TXPOWER; + for (i = 14; i < spec->num_channels; i++) { + info[i].max_power = MAX_TXPOWER; + info[i].default_power1 = DEFAULT_TXPOWER; + } } return 0; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 9ae96a626e6d..9e8b33d6d266 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1690,12 +1690,16 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->channels_info = info; tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START); - for (i = 0; i < 14; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); + for (i = 0; i < 14; i++) { + info[i].max_power = MAX_TXPOWER; + info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + } if (spec->num_channels > 14) { - for (i = 14; i < spec->num_channels; i++) - info[i].tx_power1 = DEFAULT_TXPOWER; + for (i = 14; i < spec->num_channels; i++) { + info[i].max_power = MAX_TXPOWER; + info[i].default_power1 = DEFAULT_TXPOWER; + } } return 0; diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 2aa03751c341..b72161c6aef4 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -1769,6 +1769,13 @@ struct mac_iveiv_entry { #define EEPROM_RSSI_A2_OFFSET2 FIELD16(0x00ff) #define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00) +/* + * EEPROM Maximum TX power values + */ +#define EEPROM_MAX_TX_POWER 0x0027 +#define EEPROM_MAX_TX_POWER_24GHZ FIELD16(0x00ff) +#define EEPROM_MAX_TX_POWER_5GHZ FIELD16(0xff00) + /* * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power. * This is delta in 40MHZ. diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index db4250d1c8b3..27c13d72044d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -840,27 +840,27 @@ static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev, * double meaning, and we should set a 7DBm boost flag. */ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST, - (info->tx_power1 >= 0)); + (info->default_power1 >= 0)); - if (info->tx_power1 < 0) - info->tx_power1 += 7; + if (info->default_power1 < 0) + info->default_power1 += 7; rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, - TXPOWER_A_TO_DEV(info->tx_power1)); + TXPOWER_A_TO_DEV(info->default_power1)); rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, - (info->tx_power2 >= 0)); + (info->default_power2 >= 0)); - if (info->tx_power2 < 0) - info->tx_power2 += 7; + if (info->default_power2 < 0) + info->default_power2 += 7; rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, - TXPOWER_A_TO_DEV(info->tx_power2)); + TXPOWER_A_TO_DEV(info->default_power2)); } else { rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, - TXPOWER_G_TO_DEV(info->tx_power1)); + TXPOWER_G_TO_DEV(info->default_power1)); rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, - TXPOWER_G_TO_DEV(info->tx_power2)); + TXPOWER_G_TO_DEV(info->default_power2)); } rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf)); @@ -900,13 +900,11 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, - TXPOWER_G_TO_DEV(info->tx_power1)); + rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, info->default_power1); rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, - TXPOWER_G_TO_DEV(info->tx_power2)); + rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->default_power2); rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); @@ -2226,6 +2224,13 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) default_lna_gain); rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); + rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &word); + if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_24GHZ) == 0xff) + rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_24GHZ, MAX_G_TXPOWER); + if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_5GHZ) == 0xff) + rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_5GHZ, MAX_A_TXPOWER); + rt2x00_eeprom_write(rt2x00dev, EEPROM_MAX_TX_POWER, word); + return 0; } EXPORT_SYMBOL_GPL(rt2800_validate_eeprom); @@ -2466,9 +2471,10 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; struct channel_info *info; - char *tx_power1; - char *tx_power2; + char *default_power1; + char *default_power2; unsigned int i; + unsigned short max_power; u16 eeprom; /* @@ -2566,21 +2572,26 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->channels_info = info; - tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); - tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); + rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &eeprom); + max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_24GHZ); + default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); + default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); for (i = 0; i < 14; i++) { - info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]); - info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]); + info[i].max_power = max_power; + info[i].default_power1 = TXPOWER_G_FROM_DEV(default_power1[i]); + info[i].default_power2 = TXPOWER_G_FROM_DEV(default_power2[i]); } if (spec->num_channels > 14) { - tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1); - tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); + max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_5GHZ); + default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1); + default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); for (i = 14; i < spec->num_channels; i++) { - info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]); - info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]); + info[i].max_power = max_power; + info[i].default_power1 = TXPOWER_A_FROM_DEV(default_power1[i]); + info[i].default_power2 = TXPOWER_A_FROM_DEV(default_power2[i]); } } diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 6c1ff4c15c84..0d1ff9d7c8ba 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -211,8 +211,9 @@ struct channel_info { unsigned int flags; #define GEOGRAPHY_ALLOWED 0x00000001 - short tx_power1; - short tx_power2; + short max_power; + short default_power1; + short default_power2; }; /* diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index f20d3eeeea7f..f444f0bd5978 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -605,7 +605,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, for (i = 0; i < spec->num_channels; i++) { rt2x00lib_channel(&channels[i], spec->channels[i].channel, - spec->channels_info[i].tx_power1, i); + spec->channels_info[i].max_power, i); } /* diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 6a74baf4e934..766032e0d9cb 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2605,13 +2605,17 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->channels_info = info; tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START); - for (i = 0; i < 14; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); + for (i = 0; i < 14; i++) { + info[i].max_power = MAX_TXPOWER; + info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + } if (spec->num_channels > 14) { tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START); - for (i = 14; i < spec->num_channels; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); + for (i = 14; i < spec->num_channels; i++) { + info[i].max_power = MAX_TXPOWER; + info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + } } return 0; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 6e0d82efe924..1e99a020194a 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2092,13 +2092,17 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->channels_info = info; tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START); - for (i = 0; i < 14; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); + for (i = 0; i < 14; i++) { + info[i].max_power = MAX_TXPOWER; + info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + } if (spec->num_channels > 14) { tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START); - for (i = 14; i < spec->num_channels; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); + for (i = 14; i < spec->num_channels; i++) { + info[i].max_power = MAX_TXPOWER; + info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + } } return 0; -- cgit v1.2.3 From eb9b89ea61a1b1787cf5d42ae4366c9a4c53787d Mon Sep 17 00:00:00 2001 From: Manoj Iyer Date: Tue, 23 Nov 2010 07:43:44 +0100 Subject: ALSA: hda - Enable jack sense for Thinkpad Edge 11 commit 6027277e77df2d2893d906c42f5c9f9abcb731e0 upstream. Add a quirk entry for Thinkpad Edge 11 as well as other TP Edge models. Signed-off-by: Manoj Iyer Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_conexant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index eff443ff9edd..aeea1cd0bcaa 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3039,6 +3039,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD), + SND_PCI_QUIRK(0x17aa, 0x21c8, "Thinkpad Edge 11", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD), {} -- cgit v1.2.3 From 23d8a757d065542d5e9557cc20912833085b2395 Mon Sep 17 00:00:00 2001 From: Yan Li Date: Tue, 30 Nov 2010 23:51:03 -0800 Subject: Input: synaptics - fix handling of 2-button ClickPads commit 3bfa321e662edf90fb8123a02c987c2965fa50bb upstream. Lenovo S10-3t's ClickPad is a 2-button ClickPad that reports BTN_LEFT and BTN_RIGHT as normal touchpad, unlike the 1-button ClickPad used in HP mini 210 that reports solely BTN_MIDDLE. In 0xc0-cap response, the 1-button ClickPad has the 20-bit set while 2-button ClickPad has the 8-bit set. This patch makes the kernel only handle 1-button ClickPad specially, and treat 2-button ClickPad in the same fashion as regular touchpads. This fixes kernel bug #18122 and MeeGo bug #4807. Signed-off-by: Yan Li Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/input/mouse/synaptics.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index b6aa7d20d8a3..298c8e505cc2 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -51,7 +51,8 @@ #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) #define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16) -#define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100100) +#define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ +#define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ #define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) /* synaptics modes query bits */ -- cgit v1.2.3 From 0409b72407a69538cb62bb0bc2476db0ca2b3de8 Mon Sep 17 00:00:00 2001 From: Tavis Ormandy Date: Thu, 9 Dec 2010 15:29:42 +0100 Subject: install_special_mapping skips security_file_mmap check. commit 462e635e5b73ba9a4c03913b77138cd57ce4b050 upstream. The install_special_mapping routine (used, for example, to setup the vdso) skips the security check before insert_vm_struct, allowing a local attacker to bypass the mmap_min_addr security restriction by limiting the available pages for special mappings. bprm_mm_init() also skips the check, and although I don't think this can be used to bypass any restrictions, I don't see any reason not to have the security check. $ uname -m x86_64 $ cat /proc/sys/vm/mmap_min_addr 65536 $ cat install_special_mapping.s section .bss resb BSS_SIZE section .text global _start _start: mov eax, __NR_pause int 0x80 $ nasm -D__NR_pause=29 -DBSS_SIZE=0xfffed000 -f elf -o install_special_mapping.o install_special_mapping.s $ ld -m elf_i386 -Ttext=0x10000 -Tbss=0x11000 -o install_special_mapping install_special_mapping.o $ ./install_special_mapping & [1] 14303 $ cat /proc/14303/maps 0000f000-00010000 r-xp 00000000 00:00 0 [vdso] 00010000-00011000 r-xp 00001000 00:19 2453665 /home/taviso/install_special_mapping 00011000-ffffe000 rwxp 00000000 00:00 0 [stack] It's worth noting that Red Hat are shipping with mmap_min_addr set to 4096. Signed-off-by: Tavis Ormandy Acked-by: Kees Cook Acked-by: Robert Swiecki Signed-off-by: Andi Kleen [ Changed to not drop the error code - akpm ] Reviewed-by: James Morris Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/exec.c | 5 +++++ mm/mmap.c | 16 ++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index dd8cabd27ff5..e03ddd4d2a97 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -265,6 +265,11 @@ static int __bprm_mm_init(struct linux_binprm *bprm) vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP; vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); INIT_LIST_HEAD(&vma->anon_vma_chain); + + err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); + if (err) + goto err; + err = insert_vm_struct(mm, vma); if (err) goto err; diff --git a/mm/mmap.c b/mm/mmap.c index 3a943622bd9a..073b39d32bc4 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2444,6 +2444,7 @@ int install_special_mapping(struct mm_struct *mm, unsigned long addr, unsigned long len, unsigned long vm_flags, struct page **pages) { + int ret; struct vm_area_struct *vma; vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); @@ -2461,16 +2462,23 @@ int install_special_mapping(struct mm_struct *mm, vma->vm_ops = &special_mapping_vmops; vma->vm_private_data = pages; - if (unlikely(insert_vm_struct(mm, vma))) { - kmem_cache_free(vm_area_cachep, vma); - return -ENOMEM; - } + ret = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); + if (ret) + goto out; + + ret = insert_vm_struct(mm, vma); + if (ret) + goto out; mm->total_vm += len >> PAGE_SHIFT; perf_event_mmap(vma); return 0; + +out: + kmem_cache_free(vm_area_cachep, vma); + return ret; } static DEFINE_MUTEX(mm_all_locks_mutex); -- cgit v1.2.3 From 0a67b7cf26d73ed1dbea7e99d63673b5c4aa479e Mon Sep 17 00:00:00 2001 From: Thomas Sailer Date: Tue, 14 Dec 2010 16:04:05 +0100 Subject: USB: misc: uss720.c: add another vendor/product ID commit ecc1624a2fff45780959efbcb73ace18fdb3c58d upstream. Fabio Battaglia report that he has another cable that works with this driver, so this patch adds its vendor/product ID. Signed-off-by: Thomas Sailer Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/misc/uss720.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 796e2f68f749..4ff21587ab03 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -3,7 +3,7 @@ /* * uss720.c -- USS720 USB Parport Cable. * - * Copyright (C) 1999, 2005 + * Copyright (C) 1999, 2005, 2010 * Thomas Sailer (t.sailer@alumni.ethz.ch) * * This program is free software; you can redistribute it and/or modify @@ -776,6 +776,8 @@ static const struct usb_device_id uss720_table[] = { { USB_DEVICE(0x0557, 0x2001) }, { USB_DEVICE(0x0729, 0x1284) }, { USB_DEVICE(0x1293, 0x0002) }, + { USB_DEVICE(0x1293, 0x0002) }, + { USB_DEVICE(0x050d, 0x0002) }, { } /* Terminating entry */ }; -- cgit v1.2.3 From c4234ff9aca7aef60841327560ed228cbfcf58ba Mon Sep 17 00:00:00 2001 From: Florian Faber Date: Wed, 1 Dec 2010 10:11:08 +0100 Subject: USB: ftdi_sio: Add D.O.Tec PID commit 5363cdc3c5da9bd431552cf5989ab481596f0c6d upstream. Add FTDI PID to identify D.O.Tec devices correctly. Signed-off-by: Florian Faber Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index a10942825936..506d744fd72e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -796,6 +796,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) }, { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { }, /* Optional parameter entry */ diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 393c37d36c30..77ace17fd143 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1080,6 +1080,11 @@ #define MJSG_XM_RADIO_PID 0x937A #define MJSG_HD_RADIO_PID 0x937C +/* + * D.O.Tec products (http://www.directout.eu) + */ +#define FTDI_DOTEC_PID 0x9868 + /* * Xverve Signalyzer tools (http://www.signalyzer.com/) */ -- cgit v1.2.3 From 26977d2b7fedb760cef42041f3514ab968fe78ab Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Tue, 14 Dec 2010 10:16:49 -0500 Subject: USB: usb-storage: unusual_devs entry for the Samsung YP-CP3 commit d73a9b3001f29271c2e9f2a806b05a431c5d9591 upstream. Add an unusual_devs entry for the Samsung YP-CP3 MP4 player. User was getting the following errors in dmesg: usb 2-6: reset high speed USB device using ehci_hcd and address 2 usb 2-6: reset high speed USB device using ehci_hcd and address 2 usb 2-6: reset high speed USB device using ehci_hcd and address 2 usb 2-6: USB disconnect, address 2 sd 3:0:0:0: [sdb] Assuming drive cache: write through sdb:<2>ldm_validate_partition_table(): Disk read failed. Dev sdb: unable to read RDB block 0 unable to read partition table Signed-off-by: Vitaly Kuznetsov Acked-by: Alan Stern Signed-off-by: Andi Kleen CC: Matthew Dharm Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 2c897eefadde..b51b121ae825 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -481,6 +481,13 @@ UNUSUAL_DEV( 0x04e8, 0x507c, 0x0220, 0x0220, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64), +/* Reported by Vitaly Kuznetsov */ +UNUSUAL_DEV( 0x04e8, 0x5122, 0x0000, 0x9999, + "Samsung", + "YP-CP3", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG), + /* Entry and supporting patch by Theodore Kilgore . * Device uses standards-violating 32-byte Bulk Command Block Wrappers and * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011. -- cgit v1.2.3 From 4d6d8747e1fb36b33d77a5182a6305f6839aeae9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 16 Dec 2010 15:52:30 -0800 Subject: Revert "USB: gadget: Allow function access to device ID data during bind()" commit dbb442b85a1d82f91cfe0524c4f9b3a5196a10ca upstream. This reverts commit 1ab83238740ff1e1773d5c13ecac43c60cf4aec4. Turns out this doesn't allow for the device ids to be overridden properly, so we need to revert the thing. Reported-by: Jef Driesen Cc: Robert Lukassen Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/gadget/composite.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 4b02b320e61c..b17e5c11ff49 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1018,14 +1018,6 @@ static int composite_bind(struct usb_gadget *gadget) */ usb_ep_autoconfig_reset(cdev->gadget); - /* standardized runtime overrides for device ID data */ - if (idVendor) - cdev->desc.idVendor = cpu_to_le16(idVendor); - if (idProduct) - cdev->desc.idProduct = cpu_to_le16(idProduct); - if (bcdDevice) - cdev->desc.bcdDevice = cpu_to_le16(bcdDevice); - /* composite gadget needs to assign strings for whole device (like * serial number), register function drivers, potentially update * power state and consumption, etc @@ -1037,6 +1029,14 @@ static int composite_bind(struct usb_gadget *gadget) cdev->desc = *composite->dev; cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket; + /* standardized runtime overrides for device ID data */ + if (idVendor) + cdev->desc.idVendor = cpu_to_le16(idVendor); + if (idProduct) + cdev->desc.idProduct = cpu_to_le16(idProduct); + if (bcdDevice) + cdev->desc.bcdDevice = cpu_to_le16(bcdDevice); + /* strings can't be assigned before bind() allocates the * releavnt identifiers */ -- cgit v1.2.3 From 3624cef1bd667d14284e9da384dc3569e416fe56 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 11 Dec 2010 12:19:48 +0100 Subject: p54usb: add 5 more USBIDs commit 16cad7fba037b34ca32cc0adac65bc089d969fb8 upstream. This patch adds five more USBIDs to the table. Source: http://www.linuxant.com/pipermail/driverloader/2005q3/002307.html http://wireless.kernel.org/en/users/Drivers/p54/devices (by M. Davis) Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/p54/p54usb.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 1214afe5858c..ce8fe8d1da8d 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -43,6 +43,7 @@ MODULE_FIRMWARE("isl3887usb"); static struct usb_device_id p54u_table[] __devinitdata = { /* Version 1 devices (pci chip + net2280) */ + {USB_DEVICE(0x0411, 0x0050)}, /* Buffalo WLI2-USB2-G54 */ {USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */ {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ {USB_DEVICE(0x06b9, 0x0120)}, /* Thomson SpeedTouch 120g */ @@ -56,9 +57,12 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */ {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */ {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */ + {USB_DEVICE(0x0db0, 0x6826)}, /* MSI UB54G (MS-6826) */ {USB_DEVICE(0x107b, 0x55f2)}, /* Gateway WGU-210 (Gemtek) */ {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */ + {USB_DEVICE(0x1435, 0x0210)}, /* Inventel UR054G */ {USB_DEVICE(0x1630, 0x0005)}, /* 2Wire 802.11g USB (v1) / Z-Com */ + {USB_DEVICE(0x182d, 0x096b)}, /* Sitecom WL-107 */ {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */ {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */ {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */ @@ -93,6 +97,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ {USB_DEVICE(0x1668, 0x1050)}, /* Actiontec 802UIG-1 */ {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ + {USB_DEVICE(0x2001, 0x3705)}, /* D-Link DWL-G120 rev C1 */ {USB_DEVICE(0x413c, 0x5513)}, /* Dell WLA3310 USB Wireless Adapter */ {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */ {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */ -- cgit v1.2.3 From 138d1026f3af81004fbdc9864ea56b661780dace Mon Sep 17 00:00:00 2001 From: Eduardo Costa Date: Tue, 14 Dec 2010 14:37:59 -0600 Subject: p54usb: New USB ID for Gemtek WUBI-100GW commit 56e6417b49132d4f56e9f2241d31942b90b46315 upstream. This USB ID is for the WUBI-100GW 802.11g Wireless LAN USB Device that uses p54usb. Signed-off-by: Larry Finger Signed-off-by: Eduardo Costa Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/p54/p54usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index ce8fe8d1da8d..967a200aabdc 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -61,6 +61,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x107b, 0x55f2)}, /* Gateway WGU-210 (Gemtek) */ {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */ {USB_DEVICE(0x1435, 0x0210)}, /* Inventel UR054G */ + {USB_DEVICE(0x15a9, 0x0002)}, /* Gemtek WUBI-100GW 802.11g */ {USB_DEVICE(0x1630, 0x0005)}, /* 2Wire 802.11g USB (v1) / Z-Com */ {USB_DEVICE(0x182d, 0x096b)}, /* Sitecom WL-107 */ {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */ -- cgit v1.2.3 From 1298db626792287d5c66ba71ae802cfd1db72d3f Mon Sep 17 00:00:00 2001 From: Ken Mills Date: Mon, 13 Dec 2010 15:27:27 +0000 Subject: n_gsm: Fix message length handling when building header commit be7a7411d63ccad165d66fe8e0b11b2ee336159b upstream. Fix message length handling when building header When the message length is greater than 127, the length field in the header is built incorrectly. According to the spec, when the length is less than 128 the length field is a single byte formatted as: bbbbbbb1. When it is greater than 127 then the field is two bytes of the format: bbbbbbb0 bbbbbbbb. Signed-off-by: Ken Mills Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/char/n_gsm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/n_gsm.c b/drivers/char/n_gsm.c index e4089c432f15..3bf479284c35 100644 --- a/drivers/char/n_gsm.c +++ b/drivers/char/n_gsm.c @@ -717,8 +717,8 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg) if (msg->len < 128) *--dp = (msg->len << 1) | EA; else { - *--dp = (msg->len >> 6) | EA; - *--dp = (msg->len & 127) << 1; + *--dp = (msg->len >> 7); /* bits 7 - 15 */ + *--dp = (msg->len & 127) << 1; /* bits 0 - 6 */ } } -- cgit v1.2.3 From af98113010e7815aaa0f4281f6a54bfe0c7bed3d Mon Sep 17 00:00:00 2001 From: Ken Mills Date: Mon, 13 Dec 2010 15:28:03 +0000 Subject: n_gsm: gsm_data_alloc buffer allocation could fail and it is not being checked commit 093d804611b9a38fe59753b37c29f840518406a9 upstream. gsm_data_alloc buffer allocation could fail and it is not being checked. Add check for allocated buffer and return if the buffer allocation fails. Signed-off-by: Ken Mills Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/char/n_gsm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/char/n_gsm.c b/drivers/char/n_gsm.c index 3bf479284c35..a5eeacdd7a53 100644 --- a/drivers/char/n_gsm.c +++ b/drivers/char/n_gsm.c @@ -969,6 +969,8 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, u8 *data, { struct gsm_msg *msg; msg = gsm_data_alloc(gsm, 0, dlen + 2, gsm->ftype); + if (msg == NULL) + return; msg->data[0] = (cmd & 0xFE) << 1 | EA; /* Clear C/R */ msg->data[1] = (dlen << 1) | EA; memcpy(msg->data + 2, data, dlen); -- cgit v1.2.3 From 94e0aba2a66cb0eee8c17f662c25c85a2aee141b Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 9 Dec 2010 10:29:00 -0800 Subject: xhci: Fix issue with port array setup and buggy hosts. commit f8bbeabc34aa945ab4275abc9a4dfde0aea798ca upstream. Fix two bugs with the port array setup. The first bug will only show up with broken xHCI hosts with Extended Capabilities registers that have duplicate port speed entries for the same port. The idea with the original code was to set the port_array entry to -1 if the duplicate port speed entry said the port was a different speed than the original port speed entry. That would mean that later, the port would not be exposed to the USB core. Unfortunately, I forgot a continue statement, and the port_array entry would just be overwritten in the next line. The second bug would happen if there are conflicting port speed registers (so that some entry in port_array is -1), or one of the hardware port registers was not described in the port speed registers (so that some entry in port_array is 0). The code that sets up the usb2_ports array would accidentally claim those ports. That wouldn't really cause any user-visible issues, but it is a bug. This patch should go into the stable trees that have the port array and USB 3.0 port disabling prevention patches. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/xhci-mem.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index c56afe77d9a2..8b89e0a6391d 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1670,6 +1670,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, xhci->port_array[i] = (u8) -1; } /* FIXME: Should we disable the port? */ + continue; } xhci->port_array[i] = major_revision; if (major_revision == 0x03) @@ -1748,16 +1749,20 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) return -ENOMEM; port_index = 0; - for (i = 0; i < num_ports; i++) - if (xhci->port_array[i] != 0x03) { - xhci->usb2_ports[port_index] = - &xhci->op_regs->port_status_base + - NUM_PORT_REGS*i; - xhci_dbg(xhci, "USB 2.0 port at index %u, " - "addr = %p\n", i, - xhci->usb2_ports[port_index]); - port_index++; - } + for (i = 0; i < num_ports; i++) { + if (xhci->port_array[i] == 0x03 || + xhci->port_array[i] == 0 || + xhci->port_array[i] == -1) + continue; + + xhci->usb2_ports[port_index] = + &xhci->op_regs->port_status_base + + NUM_PORT_REGS*i; + xhci_dbg(xhci, "USB 2.0 port at index %u, " + "addr = %p\n", i, + xhci->usb2_ports[port_index]); + port_index++; + } } if (xhci->num_usb3_ports) { xhci->usb3_ports = kmalloc(sizeof(*xhci->usb3_ports)* -- cgit v1.2.3 From 876c33c2acfc57b312f1743964f0c4469932fdf7 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 26 Nov 2010 10:39:54 +0100 Subject: gpio: Fix null pointer dereference while accessing rdc321x platform_data commit fa6469cb5b2d16703464c344b943e2c025cb7858 upstream. rdc321x-gpio currently fetches its driver specific data by using the platform_device->platform_data pointer, this is wrong because the mfd device which registers our platform_device has been added using mfd_add_device() which sets the platform_device->driver_data pointer instead. Signed-off-by: Florian Fainelli Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpio/rdc321x-gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/rdc321x-gpio.c b/drivers/gpio/rdc321x-gpio.c index 2762698e0204..897e0577e65e 100644 --- a/drivers/gpio/rdc321x-gpio.c +++ b/drivers/gpio/rdc321x-gpio.c @@ -135,7 +135,7 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev) struct rdc321x_gpio *rdc321x_gpio_dev; struct rdc321x_gpio_pdata *pdata; - pdata = pdev->dev.platform_data; + pdata = platform_get_drvdata(pdev); if (!pdata) { dev_err(&pdev->dev, "no platform data supplied\n"); return -ENODEV; -- cgit v1.2.3 From 1d95fe9a8ddadc8700e85f5e9d9682842a1c743c Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Tue, 21 Dec 2010 13:04:42 -0800 Subject: cs5535-gpio: don't apply errata #36 to edge detect GPIOs commit 001851659354cce436b749a793f3512a53394d80 upstream. The edge detect status GPIOs function differently from the other atomic model CS5536 GPIO registers; writing 1 to the high bits clears the GPIO, but writing 1 to the lower bits also clears the bit. This means that read-modify-write doesn't actually work for it, so don't apply the errata here. If a negative edge status gets lost after resume.. well, we tried our best! Tested-by: Daniel Drake Signed-off-by: Andres Salomon Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpio/cs5535-gpio.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c index 599f6c9e0fbf..79eb9c5a2923 100644 --- a/drivers/gpio/cs5535-gpio.c +++ b/drivers/gpio/cs5535-gpio.c @@ -56,15 +56,22 @@ static struct cs5535_gpio_chip { * registers, see include/linux/cs5535.h. */ -static void errata_outl(u32 val, unsigned long addr) +static void errata_outl(struct cs5535_gpio_chip *chip, u32 val, + unsigned int reg) { + unsigned long addr = chip->base + 0x80 + reg; + /* * According to the CS5536 errata (#36), after suspend * a write to the high bank GPIO register will clear all * non-selected bits; the recommended workaround is a * read-modify-write operation. + * + * Don't apply this errata to the edge status GPIOs, as writing + * to their lower bits will clear them. */ - val |= inl(addr); + if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS) + val |= inl(addr); outl(val, addr); } @@ -76,7 +83,7 @@ static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset, outl(1 << offset, chip->base + reg); else /* high bank register */ - errata_outl(1 << (offset - 16), chip->base + 0x80 + reg); + errata_outl(chip, 1 << (offset - 16), reg); } void cs5535_gpio_set(unsigned offset, unsigned int reg) @@ -98,7 +105,7 @@ static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset, outl(1 << (offset + 16), chip->base + reg); else /* high bank register */ - errata_outl(1 << offset, chip->base + 0x80 + reg); + errata_outl(chip, 1 << offset, reg); } void cs5535_gpio_clear(unsigned offset, unsigned int reg) -- cgit v1.2.3 From 4dfbc34551053dcf44fa3c6ab8d2fcf39bd38eea Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Tue, 21 Dec 2010 13:04:52 -0800 Subject: cs5535-gpio: handle GPIO regs where higher (clear) bits are set commit 44658a11f312fb9217674cb90b1a11cbe17fd18d upstream. The default for non-READ_BACK GPIO regs is to have the clear bits set; this means that our original errata fix was too simplistic. This changes it to the following behavior: - when setting GPIOs, ignore the higher order bits (they're for clearing, we don't need to care about them). - when clearing GPIOs, keep all the bits, but unset (via XOR) the lower order bit that negates the clear bit that we care about. That is, if we're clearing GPIO 26 (val = 0x04000000), we first XOR what's currently in the register with 0x0400 (GPIO 26's SET bit), and then OR that with the GPIO 26's CLEAR bit. Tested-by: Daniel Drake Signed-off-by: Andres Salomon Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpio/cs5535-gpio.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c index 79eb9c5a2923..d3e55a0ae92b 100644 --- a/drivers/gpio/cs5535-gpio.c +++ b/drivers/gpio/cs5535-gpio.c @@ -70,8 +70,12 @@ static void errata_outl(struct cs5535_gpio_chip *chip, u32 val, * Don't apply this errata to the edge status GPIOs, as writing * to their lower bits will clear them. */ - if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS) - val |= inl(addr); + if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS) { + if (val & 0xffff) + val |= (inl(addr) & 0xffff); /* ignore the high bits */ + else + val |= (inl(addr) ^ (val >> 16)); + } outl(val, addr); } -- cgit v1.2.3 From 84da397234ceec8449444598d8d72668d7f5bb8c Mon Sep 17 00:00:00 2001 From: Yauhen Kharuzhy Date: Thu, 25 Nov 2010 12:11:51 +0200 Subject: mmc: at91_mci: fix multiblock SDIO transfers commit a2255ff45143001fecbc5e5a4b58fcb999d393ae upstream. The AT91 MCI has special SDIO transfer types: SDIO block and SDIO byte transfers, but at91_mci driver doesn't use them and handles all SDIO transfers as ordinary MMC block transfers. This causes problems for multiple-block SDIO transfers (in particular for 256-bytes blocks). Fix this situation by checking the opcode for SDIO CMD53 and setting the transfer type in the AT91_MCI_CMDR register properly. This patch was tested with libertas SDIO driver: problem with TX timeouts on big packets was eliminated. Signed-off-by: Yauhen Kharuzhy Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/arm/mach-at91/include/mach/at91_mci.h | 2 ++ drivers/mmc/host/at91_mci.c | 13 +++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-at91/include/mach/at91_mci.h b/arch/arm/mach-at91/include/mach/at91_mci.h index 57f8ee154943..27ac6f550fe3 100644 --- a/arch/arm/mach-at91/include/mach/at91_mci.h +++ b/arch/arm/mach-at91/include/mach/at91_mci.h @@ -74,6 +74,8 @@ #define AT91_MCI_TRTYP_BLOCK (0 << 19) #define AT91_MCI_TRTYP_MULTIPLE (1 << 19) #define AT91_MCI_TRTYP_STREAM (2 << 19) +#define AT91_MCI_TRTYP_SDIO_BYTE (4 << 19) +#define AT91_MCI_TRTYP_SDIO_BLOCK (5 << 19) #define AT91_MCI_BLKR 0x18 /* Block Register */ #define AT91_MCI_BLKR_BCNT(n) ((0xffff & (n)) << 0) /* Block count */ diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index 5f3a599ead07..e29a5fb5bc7e 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c @@ -68,6 +68,7 @@ #include #include +#include #include #include @@ -492,10 +493,14 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command else if (data->flags & MMC_DATA_WRITE) cmdr |= AT91_MCI_TRCMD_START; - if (data->flags & MMC_DATA_STREAM) - cmdr |= AT91_MCI_TRTYP_STREAM; - if (data->blocks > 1) - cmdr |= AT91_MCI_TRTYP_MULTIPLE; + if (cmd->opcode == SD_IO_RW_EXTENDED) { + cmdr |= AT91_MCI_TRTYP_SDIO_BLOCK; + } else { + if (data->flags & MMC_DATA_STREAM) + cmdr |= AT91_MCI_TRTYP_STREAM; + if (data->blocks > 1) + cmdr |= AT91_MCI_TRTYP_MULTIPLE; + } } else { block_length = 0; -- cgit v1.2.3 From 3fa84c1cbf8baca625f08f475338193ee9be1eea Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Fri, 10 Dec 2010 19:14:32 +0100 Subject: mmc: atmel-mci: fix multiblock SDIO transfers commit 2f1d791882d21a4002a719fb016a1ac21c8bd6b7 upstream. Based on report made by Yauhen in: "MMC: Fix multiblock SDIO transfers in AT91 MCI" patch, I report those changes to the brother driver: atmel-mci. So, this patch sets SDIO transfer types: SDIO block and SDIO byte transfers instead of using ordinary MMC block transfers. It is checking opcode for SDIO CMD53 and setting transfer type in MCI_CMDR register properly. Reported-by: Yauhen Kharuzhy Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/mmc/host/atmel-mci.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 95ef864ad8f9..3a569bfe3886 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -532,12 +533,17 @@ static u32 atmci_prepare_command(struct mmc_host *mmc, data = cmd->data; if (data) { cmdr |= MCI_CMDR_START_XFER; - if (data->flags & MMC_DATA_STREAM) - cmdr |= MCI_CMDR_STREAM; - else if (data->blocks > 1) - cmdr |= MCI_CMDR_MULTI_BLOCK; - else - cmdr |= MCI_CMDR_BLOCK; + + if (cmd->opcode == SD_IO_RW_EXTENDED) { + cmdr |= MCI_CMDR_SDIO_BLOCK; + } else { + if (data->flags & MMC_DATA_STREAM) + cmdr |= MCI_CMDR_STREAM; + else if (data->blocks > 1) + cmdr |= MCI_CMDR_MULTI_BLOCK; + else + cmdr |= MCI_CMDR_BLOCK; + } if (data->flags & MMC_DATA_READ) cmdr |= MCI_CMDR_TRDIR_READ; -- cgit v1.2.3 From 01dda54376c56e99e475193d6c112f05476e5280 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 10 Dec 2010 08:40:31 +0100 Subject: mmc: Fix re-probing with PM_POST_RESTORE notification commit 274476f8fe0b6ac9bac542cc39de12c3dd0f43f6 upstream. In the error-path where PM notifies PM_POST_RESTORE, the rescan-blockage should be cleared as well. Otherwise it'll be never re-probed. Also, as a bonus, this fixes a bug in S4 with user-mode suspend in the current code, as it sends PM_POST_RESTORE instead of PM_POST_HIBERNATION wrongly. Signed-off-by: Takashi Iwai Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/mmc/core/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 365997e28f32..c9a876602b32 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1366,6 +1366,7 @@ int mmc_pm_notify(struct notifier_block *notify_block, case PM_POST_SUSPEND: case PM_POST_HIBERNATION: + case PM_POST_RESTORE: spin_lock_irqsave(&host->lock, flags); host->rescan_disable = 0; -- cgit v1.2.3 From 55eb2febc4ec26d4ecde0964af63e4f152d353bf Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Wed, 29 Dec 2010 21:55:28 +0800 Subject: fix freeing user_struct in user cache commit 4ef9e11d6867f88951e30db910fa015300e31871 upstream. When racing on adding into user cache, the new allocated from mm slab is freed without putting user namespace. Since the user namespace is already operated by getting, putting has to be issued. Signed-off-by: Hillf Danton Acked-by: Serge Hallyn Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/user.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/user.c b/kernel/user.c index 7e72614b736d..8ce395f74d47 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -157,6 +157,7 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid) spin_lock_irq(&uidhash_lock); up = uid_hash_find(uid, hashent); if (up) { + put_user_ns(ns); key_put(new->uid_keyring); key_put(new->session_keyring); kmem_cache_free(uid_cachep, new); -- cgit v1.2.3 From 39ab95f709fd14c0542ad9e5eaebebc30c681094 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 21 Dec 2010 17:24:24 -0800 Subject: rtc: rs5c372: fix buffer size commit 118364948fad7b6c0469ef2d3ddaee447d7a0b5f upstream. Match the buffer size to the amount of initialized values. Before, it was one too big and thus destroyed the neighbouring register causing the clock to run at false speeds. Reported-by: Andre van Rooyen Signed-off-by: Wolfram Sang Signed-off-by: Andi Kleen Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-rs5c372.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 90cf0a6ff23e..dd14e202c2c8 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -207,7 +207,7 @@ static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm) static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) { struct rs5c372 *rs5c = i2c_get_clientdata(client); - unsigned char buf[8]; + unsigned char buf[7]; int addr; dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d " -- cgit v1.2.3 From bf4a80cbf1ec11260c1a458586f2433431646994 Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Sat, 25 Dec 2010 11:57:09 +0200 Subject: RAMOOPS: Don't overflow over non-allocated regions commit 1873bb8115e678ad9fd0aac9dbbc68383bc36e06 upstream. The current code mis-calculates the ramoops header size, leading to an overflow over the next record at best, or over a non-allocated region at worst. Fix that calculation. Signed-off-by: Ahmed S. Darwish Acked-by: Marco Stornelli Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/char/ramoops.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c index 74f00b5ffa36..9445f48c692f 100644 --- a/drivers/char/ramoops.c +++ b/drivers/char/ramoops.c @@ -27,7 +27,6 @@ #include #define RAMOOPS_KERNMSG_HDR "====" -#define RAMOOPS_HEADER_SIZE (5 + sizeof(struct timeval)) #define RECORD_SIZE 4096 @@ -63,8 +62,8 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper, struct ramoops_context, dump); unsigned long s1_start, s2_start; unsigned long l1_cpy, l2_cpy; - int res; - char *buf; + int res, hdr_size; + char *buf, *buf_orig; struct timeval timestamp; /* Only dump oopses if dump_oops is set */ @@ -72,6 +71,8 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper, return; buf = (char *)(cxt->virt_addr + (cxt->count * RECORD_SIZE)); + buf_orig = buf; + memset(buf, '\0', RECORD_SIZE); res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR); buf += res; @@ -79,8 +80,9 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper, res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, (long)timestamp.tv_usec); buf += res; - l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE)); - l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE) - l2_cpy); + hdr_size = buf - buf_orig; + l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - hdr_size)); + l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - hdr_size) - l2_cpy); s2_start = l2 - l2_cpy; s1_start = l1 - l1_cpy; -- cgit v1.2.3 From c28dd2596ae32a0c500745f4061648a0045fed2c Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 26 Nov 2010 10:39:55 +0100 Subject: watchdog: Fix null pointer dereference while accessing rdc321x platform_data commit 3b3c1f24e96c411a95daabb6af9e09c5381f713b upstream. rdc321x-wdt currently fetches its driver specific data by using the platform_device->platform_data pointer, this is wrong because the mfd device which registers our platform_device has been added using mfd_add_device() which sets the platform_device->driver_data pointer instead. Signed-off-by: Florian Fainelli Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/watchdog/rdc321x_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c index 428f8a1583e8..3939e53f5f98 100644 --- a/drivers/watchdog/rdc321x_wdt.c +++ b/drivers/watchdog/rdc321x_wdt.c @@ -231,7 +231,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev) struct resource *r; struct rdc321x_wdt_pdata *pdata; - pdata = pdev->dev.platform_data; + pdata = platform_get_drvdata(pdev); if (!pdata) { dev_err(&pdev->dev, "no platform data supplied\n"); return -ENODEV; -- cgit v1.2.3 From 26120280fe178d45390f28394e2d31399c04506d Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 3 Jan 2011 12:15:14 +0100 Subject: arch/x86/oprofile/op_model_amd.c: Perform initialisation on a single CPU commit c7c25802b39c443b3745cfa973dc49a97a3491f8 upstream. Disable preemption in init_ibs(). The function only checks the ibs capabilities and sets up pci devices (if necessary). It runs only on one cpu but operates with the local APIC and some MSRs, thus it is better to disable preemption. [ 7.034377] BUG: using smp_processor_id() in preemptible [00000000] code: modprobe/483 [ 7.034385] caller is setup_APIC_eilvt+0x155/0x180 [ 7.034389] Pid: 483, comm: modprobe Not tainted 2.6.37-rc1-20101110+ #1 [ 7.034392] Call Trace: [ 7.034400] [] debug_smp_processor_id+0xd2/0xf0 [ 7.034404] [] setup_APIC_eilvt+0x155/0x180 [ ... ] Addresses https://bugzilla.kernel.org/show_bug.cgi?id=22812 Reported-by: Signed-off-by: Robert Richter Signed-off-by: Andi Kleen Cc: oprofile-list@lists.sourceforge.net Cc: Peter Zijlstra Cc: Frederic Weisbecker Cc: Rafael J. Wysocki Cc: Dan Carpenter Cc: Andrew Morton LKML-Reference: <20110103111514.GM4739@erda.amd.com> [ small cleanups ] Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/oprofile/op_model_amd.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index b67a6b5aa8d4..42623310c968 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -484,21 +484,29 @@ static int __init_ibs_nmi(void) return 0; } -/* initialize the APIC for the IBS interrupts if available */ +/* + * check and reserve APIC extended interrupt LVT offset for IBS if + * available + * + * init_ibs() preforms implicitly cpu-local operations, so pin this + * thread to its current CPU + */ + static void init_ibs(void) { - ibs_caps = get_ibs_caps(); + preempt_disable(); + ibs_caps = get_ibs_caps(); if (!ibs_caps) - return; + goto out; - if (__init_ibs_nmi()) { + if (__init_ibs_nmi() < 0) ibs_caps = 0; - return; - } + else + printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps); - printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", - (unsigned)ibs_caps); +out: + preempt_enable(); } static int (*create_arch_files)(struct super_block *sb, struct dentry *root); -- cgit v1.2.3 From 848d070ae77a340275678ce27fde5c831e299e64 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Dec 2010 16:25:43 +0000 Subject: mfd: Support additional parent IDs for wm831x commit b93cef556162b0f33399bfe5f307c54f51554e09 upstream. Some newer device revisions add a second parent ID. Support this in the device validity checks done at startup. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/mfd/wm831x-core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 1a968f34d679..8d7182e24985 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -1463,7 +1463,11 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret); goto err; } - if (ret != 0x6204) { + switch (ret) { + case 0x6204: + case 0x6246: + break; + default: dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret); ret = -EINVAL; goto err; -- cgit v1.2.3 From 87e27023b169b23410b59e24e579d8d9d55136a8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 24 Nov 2010 18:01:39 +0000 Subject: mfd: Supply IRQ base for WM832x devices commit bd7c72ed18d719c1fb0fdf6ff9042d8ab78fdf71 upstream. Without this the IRQ base will not be correctly configured for the subdevices. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/mfd/wm831x-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 8d7182e24985..0f8757259d17 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -1608,7 +1608,7 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) case WM8320: ret = mfd_add_devices(wm831x->dev, -1, wm8320_devs, ARRAY_SIZE(wm8320_devs), - NULL, 0); + NULL, wm831x->irq_base); break; default: -- cgit v1.2.3 From a3f86d59f4f072da1d289a9c12cd4c10fbc3e065 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 20 Dec 2010 12:35:04 -0500 Subject: drm/radeon/kms/evergreen: reset the grbm blocks at resume and init commit 86f5c9edbb3bac37cc8cee6528a929005ba72aad upstream. This fixes module reloading and resume as the gfx block seems to be left in a bad state in some cases. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/evergreen.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 82cc369a85ec..b7e60e562c41 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2080,6 +2080,11 @@ int evergreen_resume(struct radeon_device *rdev) { int r; + /* reset the asic, the gfx blocks are often in a bad state + * after the driver is unloaded or after a resume + */ + if (radeon_asic_reset(rdev)) + dev_warn(rdev->dev, "GPU reset failed !\n"); /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw, * posting will perform necessary task to bring back GPU into good * shape. @@ -2181,6 +2186,11 @@ int evergreen_init(struct radeon_device *rdev) r = radeon_atombios_init(rdev); if (r) return r; + /* reset the asic, the gfx blocks are often in a bad state + * after the driver is unloaded or after a resume + */ + if (radeon_asic_reset(rdev)) + dev_warn(rdev->dev, "GPU reset failed !\n"); /* Post card if necessary */ if (!evergreen_card_posted(rdev)) { if (!rdev->bios) { -- cgit v1.2.3 From ee8aa621efcdd5dd76a91f0085e1f2dc940cb3b8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 20 Dec 2010 12:35:03 -0500 Subject: drm/radeon/kms: fix evergreen asic reset commit 9f0c4f9c2f835eee1bbb93f96bf9483d56f1892b upstream. Only reset the grbm blocks, srbm tends to lock the GPU if not done properly and in most cases is not necessary. Also, no need to call asic init after reset the grbm blocks. Signed-off-by: Alex Deucher Signed-off-by: Andi Kleen Reviewed-by: Jerome Glisse Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index b7e60e562c41..c500616bec6b 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1406,7 +1406,6 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev) static int evergreen_gpu_soft_reset(struct radeon_device *rdev) { struct evergreen_mc_save save; - u32 srbm_reset = 0; u32 grbm_reset = 0; dev_info(rdev->dev, "GPU softreset \n"); @@ -1445,16 +1444,6 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev) udelay(50); WREG32(GRBM_SOFT_RESET, 0); (void)RREG32(GRBM_SOFT_RESET); - - /* reset all the system blocks */ - srbm_reset = SRBM_SOFT_RESET_ALL_MASK; - - dev_info(rdev->dev, " SRBM_SOFT_RESET=0x%08X\n", srbm_reset); - WREG32(SRBM_SOFT_RESET, srbm_reset); - (void)RREG32(SRBM_SOFT_RESET); - udelay(50); - WREG32(SRBM_SOFT_RESET, 0); - (void)RREG32(SRBM_SOFT_RESET); /* Wait a little for things to settle down */ udelay(50); dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", @@ -1465,10 +1454,6 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev) RREG32(GRBM_STATUS_SE1)); dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", RREG32(SRBM_STATUS)); - /* After reset we need to reinit the asic as GPU often endup in an - * incoherent state. - */ - atom_asic_init(rdev->mode_info.atom_context); evergreen_mc_resume(rdev, &save); return 0; } -- cgit v1.2.3 From 2f33a030c672eff1af2a5414c497a10d66b80982 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 20 Dec 2010 11:22:29 -0500 Subject: drm/radeon/kms: reorder display resume to avoid problems commit a93f344d3c04e4b84490c65f2a574387c593be40 upstream. On resume, we were attemping to unblank the displays before the timing and plls had be reprogrammed which led to atom timeouts waiting for things that are not yet programmed. Re-program the mode first, then reset the dpms state. This fixes the infamous atombios timeouts on resume. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/atombios_crtc.c | 3 ++- drivers/gpu/drm/radeon/radeon_device.c | 9 ++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 1d67f4de7f1a..6e7b0399bfa3 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -259,7 +259,8 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); - atombios_blank_crtc(crtc, ATOM_ENABLE); + if (radeon_crtc->enabled) + atombios_blank_crtc(crtc, ATOM_ENABLE); if (ASIC_IS_DCE3(rdev)) atombios_enable_crtc_memreq(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_DISABLE); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index a7184636dcb4..cb5b4ceae7c8 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -799,11 +799,6 @@ int radeon_resume_kms(struct drm_device *dev) radeon_pm_resume(rdev); radeon_restore_bios_scratch_regs(rdev); - /* turn on display hw */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); - } - radeon_fbdev_set_suspend(rdev, 0); release_console_sem(); @@ -811,6 +806,10 @@ int radeon_resume_kms(struct drm_device *dev) radeon_hpd_init(rdev); /* blat the mode back in */ drm_helper_resume_force_mode(dev); + /* turn on display hw */ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + } return 0; } -- cgit v1.2.3 From 02e8aefffbe5cc35c1f1b090ca8d8b6fce4da46a Mon Sep 17 00:00:00 2001 From: David Flynn Date: Wed, 8 Dec 2010 16:10:21 +0000 Subject: drm/i915/dp: Fix I2C/EDID handling with active DisplayPort to DVI converter commit 8316f33766a82907c694267ff911e45e256f09f9 upstream. The DisplayPort standard (1.1a) states that: The I2C-over-AUX Reply field is valid only when Native AUX CH Reply field is AUX_ACK (00). When Native AUX CH Reply field is not 00, then, I2C-over-AUX Reply field must be 00 and be ignored. This fixes broken EDID reading when using an active DisplayPort to duallink DVI converter. If the AUX CH replier chooses to defer the transaction, a short read occurs and erroneous data is returned as the i2c reply due to a lack of length checking and failure to check for AUX ACK. As a result, broken EDIDs can look like: 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef 00: bc bc bc ff bc bc bc ff bc bc bc ac bc bc bc 45 ???.???.???????E 10: bc bc bc 10 bc bc bc 34 bc bc bc ee bc bc bc 4c ???????4???????L 20: bc bc bc 50 bc bc bc 00 bc bc bc 40 bc bc bc 00 ???P???.???@???. 30: bc bc bc 01 bc bc bc 01 bc bc bc a0 bc bc bc 40 ???????????????@ 40: bc bc bc 00 bc bc bc 00 bc bc bc 00 bc bc bc 55 ???.???.???.???U 50: bc bc bc 35 bc bc bc 31 bc bc bc 20 bc bc bc fc ???5???1??? ???? 60: bc bc bc 4c bc bc bc 34 bc bc bc 46 bc bc bc 00 ???L???4???F???. 70: bc bc bc 38 bc bc bc 11 bc bc bc 20 bc bc bc 20 ???8??????? ??? 80: bc bc bc ff bc bc bc ff bc bc bc ff bc bc bc ff ???.???.???.???. ... which can lead to: [drm:drm_edid_block_valid] *ERROR* EDID checksum is invalid, remainder [drm:drm_edid_block_valid] *ERROR* Raw EDID: <3>30 30 30 30 30 30 30 32 38 32 30 32 63 63 31 61 000000028202cc1a <3>28 00 02 8c 00 00 00 00 18 00 00 00 00 00 00 00 (............... <3>20 4c 61 73 74 20 62 65 61 63 6f 6e 3a 20 33 32 Last beacon: 32 <3>32 30 6d 73 20 61 67 6f 46 00 05 8c 00 00 00 00 20ms agoF....... <3>36 00 00 00 00 00 00 00 00 0c 57 69 2d 46 69 20 6.........Wi-Fi <3>52 6f 75 74 65 72 01 08 82 84 8b 96 24 30 48 6c Router......$0Hl <3>03 01 01 06 02 00 00 2a 01 00 2f 01 00 32 04 0c .......*../..2.. <3>12 18 60 dd 09 00 10 18 02 00 00 01 00 00 18 00 ..`............. Signed-off-by: David Flynn Signed-off-by: Andi Kleen [ickle: fix up some surrounding checkpatch warnings] Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_dp.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d9de8f12230d..15ae3b631583 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -416,6 +416,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, uint16_t address = algo_data->address; uint8_t msg[5]; uint8_t reply[2]; + unsigned retry; int msg_bytes; int reply_bytes; int ret; @@ -450,14 +451,33 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, break; } - for (;;) { - ret = intel_dp_aux_ch(intel_encoder, - msg, msg_bytes, - reply, reply_bytes); + for (retry = 0; retry < 5; retry++) { + ret = intel_dp_aux_ch(intel_encoder, + msg, msg_bytes, + reply, reply_bytes); if (ret < 0) { DRM_DEBUG_KMS("aux_ch failed %d\n", ret); return ret; } + + switch (reply[0] & AUX_NATIVE_REPLY_MASK) { + case AUX_NATIVE_REPLY_ACK: + /* I2C-over-AUX Reply field is only valid + * when paired with AUX ACK. + */ + break; + case AUX_NATIVE_REPLY_NACK: + DRM_DEBUG_KMS("aux_ch native nack\n"); + return -EREMOTEIO; + case AUX_NATIVE_REPLY_DEFER: + udelay(100); + continue; + default: + DRM_ERROR("aux_ch invalid native reply 0x%02x\n", + reply[0]); + return -EREMOTEIO; + } + switch (reply[0] & AUX_I2C_REPLY_MASK) { case AUX_I2C_REPLY_ACK: if (mode == MODE_I2C_READ) { @@ -465,17 +485,20 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, } return reply_bytes - 1; case AUX_I2C_REPLY_NACK: - DRM_DEBUG_KMS("aux_ch nack\n"); + DRM_DEBUG_KMS("aux_i2c nack\n"); return -EREMOTEIO; case AUX_I2C_REPLY_DEFER: - DRM_DEBUG_KMS("aux_ch defer\n"); + DRM_DEBUG_KMS("aux_i2c defer\n"); udelay(100); break; default: - DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]); + DRM_ERROR("aux_i2c invalid reply 0x%02x\n", reply[0]); return -EREMOTEIO; } } + + DRM_ERROR("too many retries, giving up\n"); + return -EREMOTEIO; } static int -- cgit v1.2.3 From 6e3cd473b8826c8ca545135f5b49ddb73f15d54f Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Sat, 25 Dec 2010 16:23:40 -0500 Subject: sound: Prevent buffer overflow in OSS load_mixer_volumes commit d81a12bc29ae4038770e05dce4ab7f26fd5880fb upstream. The load_mixer_volumes() function, which can be triggered by unprivileged users via the SOUND_MIXER_SETLEVELS ioctl, is vulnerable to a buffer overflow. Because the provided "name" argument isn't guaranteed to be NULL terminated at the expected 32 bytes, it's possible to overflow past the end of the last element in the mixer_vols array. Further exploitation can result in an arbitrary kernel write (via subsequent calls to load_mixer_volumes()) leading to privilege escalation, or arbitrary kernel reads via get_mixer_levels(). In addition, the strcmp() may leak bytes beyond the mixer_vols array. Signed-off-by: Dan Rosenberg Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/oss/soundcard.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index 19ce86d445c2..aa26fd462831 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c @@ -86,7 +86,7 @@ int *load_mixer_volumes(char *name, int *levels, int present) int i, n; for (i = 0; i < num_mixer_volumes; i++) { - if (strcmp(name, mixer_vols[i].name) == 0) { + if (strncmp(name, mixer_vols[i].name, 32) == 0) { if (present) mixer_vols[i].num = i; return mixer_vols[i].levels; @@ -98,7 +98,7 @@ int *load_mixer_volumes(char *name, int *levels, int present) } n = num_mixer_volumes++; - strcpy(mixer_vols[n].name, name); + strncpy(mixer_vols[n].name, name, 32); if (present) mixer_vols[n].num = n; -- cgit v1.2.3 From d1e1c53f02d8dd402e6a88d5976c2038087d8539 Mon Sep 17 00:00:00 2001 From: Saeed Bishara Date: Tue, 21 Dec 2010 16:53:39 +0200 Subject: mv_xor: fix race in tasklet function commit 8333f65ef094e47020cd01452b4637e7daf5a77f upstream. use mv_xor_slot_cleanup() instead of __mv_xor_slot_cleanup() as the former function aquires the spin lock that needed to protect the drivers data. Signed-off-by: Saeed Bishara Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/dma/mv_xor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 411d5bf50fc4..a25f5f61e0e0 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -449,7 +449,7 @@ mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan) static void mv_xor_tasklet(unsigned long data) { struct mv_xor_chan *chan = (struct mv_xor_chan *) data; - __mv_xor_slot_cleanup(chan); + mv_xor_slot_cleanup(chan); } static struct mv_xor_desc_slot * -- cgit v1.2.3 From 7ca39620483ad7dbd833970bd6c7c6246edcd573 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Mon, 3 Jan 2011 14:59:10 -0800 Subject: ima: fix add LSM rule bug commit 867c20265459d30a01b021a9c1e81fb4c5832aa9 upstream. If security_filter_rule_init() doesn't return a rule, then not everything is as fine as the return code implies. This bug only occurs when the LSM (eg. SELinux) is disabled at runtime. Adding an empty LSM rule causes ima_match_rules() to always succeed, ignoring any remaining rules. default IMA TCB policy: # PROC_SUPER_MAGIC dont_measure fsmagic=0x9fa0 # SYSFS_MAGIC dont_measure fsmagic=0x62656572 # DEBUGFS_MAGIC dont_measure fsmagic=0x64626720 # TMPFS_MAGIC dont_measure fsmagic=0x01021994 # SECURITYFS_MAGIC dont_measure fsmagic=0x73636673 < LSM specific rule > dont_measure obj_type=var_log_t measure func=BPRM_CHECK measure func=FILE_MMAP mask=MAY_EXEC measure func=FILE_CHECK mask=MAY_READ uid=0 Thus without the patch, with the boot parameters 'tcb selinux=0', adding the above 'dont_measure obj_type=var_log_t' rule to the default IMA TCB measurement policy, would result in nothing being measured. The patch prevents the default TCB policy from being replaced. Signed-off-by: Mimi Zohar Signed-off-by: Andi Kleen Cc: James Morris Acked-by: Serge Hallyn Cc: David Safford Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- security/integrity/ima/ima_policy.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index aef8c0a923ab..d661afbe474c 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -253,6 +253,8 @@ static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry, result = security_filter_rule_init(entry->lsm[lsm_rule].type, Audit_equal, args, &entry->lsm[lsm_rule].rule); + if (!entry->lsm[lsm_rule].rule) + return -EINVAL; return result; } -- cgit v1.2.3 From e460ad502aa1e940b4069734d8d96cc4a303062e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 3 Dec 2010 15:19:13 +0100 Subject: libata-sff: fix HSM_ST_ERR handling in __ata_sff_port_intr() commit 687a993339c4f3a63654746230da3aab8bbdbffd upstream. While separating out BMDMA irq handler from SFF, commit c3b28894 (libata-sff: separate out BMDMA irq handler) incorrectly made __ata_sff_port_intr() consider an IRQ to be an idle one if the host state was transitioned to HSM_ST_ERR by ata_bmdma_port_intr(). This makes BMDMA drivers ignore IRQs reporting host bus error which leads to timeouts instead of triggering EH immediately. Fix it by making __ata_sff_port_intr() consider the IRQ to be an idle one iff the state is HSM_ST_IDLE. This is equivalent to adding HSM_ST_ERR to the "break"ing case but less error-prone. Signed-off-by: Tejun Heo Signed-off-by: Andi Kleen Reported-by: Antonio Toma Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-sff.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index cde20ffa1116..804d8f8513f3 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -1515,11 +1515,10 @@ static unsigned int __ata_sff_port_intr(struct ata_port *ap, if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) return ata_sff_idle_irq(ap); break; - case HSM_ST: - case HSM_ST_LAST: - break; - default: + case HSM_ST_IDLE: return ata_sff_idle_irq(ap); + default: + break; } /* check main status, clearing INTRQ if needed */ -- cgit v1.2.3 From 9c7d253b2ba4a6621b19e439cdb1441e802374e5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Dec 2010 10:15:07 +0100 Subject: mac80211: fix mesh forwarding commit b51aff057c9d0ef6c529dc25fd9f775faf7b6c63 upstream. Under memory pressure, the mac80211 mesh code may helpfully print a message that it failed to clone a mesh frame and then will proceed to crash trying to use it anyway. Fix that. Signed-off-by: Johannes Berg Acked-by: Javier Cardona Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/mac80211/rx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index af775e9bf60a..3a39074df1d7 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1707,9 +1707,11 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) fwd_skb = skb_copy(skb, GFP_ATOMIC); - if (!fwd_skb && net_ratelimit()) + if (!fwd_skb && net_ratelimit()) { printk(KERN_DEBUG "%s: failed to clone mesh frame\n", sdata->name); + goto out; + } fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); @@ -1747,6 +1749,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) } } + out: if (is_multicast_ether_addr(hdr->addr1) || sdata->dev->flags & IFF_PROMISC) return RX_CONTINUE; -- cgit v1.2.3 From 04d11148665af608fcc9223ddc26cee1901df6e1 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Tue, 28 Dec 2010 17:20:02 -0500 Subject: ALSA: hda: Use LPIB quirk for Dell Inspiron m101z/1120 commit e03fa055bc126e536c7f65862e08a9b143138ea9 upstream. Sjoerd Simons reports that, without using position_fix=1, recording experiences overruns. Work around that by applying the LPIB quirk for his hardware. Reported-and-tested-by: Sjoerd Simons Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/hda_intel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index a5f6774b630f..c4c9217394e0 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2295,6 +2295,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB), + SND_PCI_QUIRK(0x1028, 0x0470, "Dell Inspiron 1120", POS_FIX_LPIB), SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), -- cgit v1.2.3 From 67410e0b0c39bf7d83834232cd51493c902ff7a9 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Wed, 8 Dec 2010 11:05:42 +0100 Subject: Sched: fix skip_clock_update optimization commit f26f9aff6aaf67e9a430d16c266f91b13a5bff64 upstream. idle_balance() drops/retakes rq->lock, leaving the previous task vulnerable to set_tsk_need_resched(). Clear it after we return from balancing instead, and in setup_thread_stack() as well, so no successfully descheduled or never scheduled task has it set. Need resched confused the skip_clock_update logic, which assumes that the next call to update_rq_clock() will come nearly immediately after being set. Make the optimization robust against the waking a sleeper before it sucessfully deschedules case by checking that the current task has not been dequeued before setting the flag, since it is that useless clock update we're trying to save, and clear unconditionally in schedule() proper instead of conditionally in put_prev_task(). Signed-off-by: Mike Galbraith Signed-off-by: Andi Kleen Reported-by: Bjoern B. Brandenburg Tested-by: Yong Zhang Signed-off-by: Peter Zijlstra LKML-Reference: <1291802742.1417.9.camel@marge.simson.net> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/fork.c | 1 + kernel/sched.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/fork.c b/kernel/fork.c index e96c0cd67e4a..bc0af81f4f33 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -272,6 +272,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) setup_thread_stack(tsk, orig); clear_user_return_notifier(tsk); + clear_tsk_need_resched(tsk); stackend = end_of_stack(tsk); *stackend = STACK_END_MAGIC; /* for overflow detection */ diff --git a/kernel/sched.c b/kernel/sched.c index 4c89e4feff60..d4f71b01136c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -564,7 +564,7 @@ void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags) * A queue event has occurred, and we're going to schedule. In * this case, we can save a useless back to back clock update. */ - if (test_tsk_need_resched(p)) + if (rq->curr->se.on_rq && test_tsk_need_resched(rq->curr)) rq->skip_clock_update = 1; } @@ -3657,7 +3657,6 @@ static void put_prev_task(struct rq *rq, struct task_struct *prev) { if (prev->se.on_rq) update_rq_clock(rq); - rq->skip_clock_update = 0; prev->sched_class->put_prev_task(rq, prev); } @@ -3720,7 +3719,6 @@ need_resched_nonpreemptible: hrtick_clear(rq); raw_spin_lock_irq(&rq->lock); - clear_tsk_need_resched(prev); if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { if (unlikely(signal_pending_state(prev->state, prev))) @@ -3737,6 +3735,8 @@ need_resched_nonpreemptible: put_prev_task(rq, prev); next = pick_next_task(rq); + clear_tsk_need_resched(prev); + rq->skip_clock_update = 0; if (likely(prev != next)) { sched_info_switch(prev, next); -- cgit v1.2.3 From 3b5dd0d60f277a0f991e548894defeb6665d2c20 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Wed, 1 Dec 2010 19:41:49 +0100 Subject: block: Deprecate QUEUE_FLAG_CLUSTER and use queue_limits instead commit e692cb668fdd5a712c6ed2a2d6f2a36ee83997b4 upstream. When stacking devices, a request_queue is not always available. This forced us to have a no_cluster flag in the queue_limits that could be used as a carrier until the request_queue had been set up for a metadevice. There were several problems with that approach. First of all it was up to the stacking device to remember to set queue flag after stacking had completed. Also, the queue flag and the queue limits had to be kept in sync at all times. We got that wrong, which could lead to us issuing commands that went beyond the max scatterlist limit set by the driver. The proper fix is to avoid having two flags for tracking the same thing. We deprecate QUEUE_FLAG_CLUSTER and use the queue limit directly in the block layer merging functions. The queue_limit 'no_cluster' is turned into 'cluster' to avoid double negatives and to ease stacking. Clustering defaults to being enabled as before. The queue flag logic is removed from the stacking function, and explicitly setting the cluster flag is no longer necessary in DM and MD. Reported-by: Ed Lin Signed-off-by: Martin K. Petersen Acked-by: Mike Snitzer Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- block/blk-merge.c | 6 +++--- block/blk-settings.c | 25 ++----------------------- block/blk-sysfs.c | 2 +- drivers/md/dm-table.c | 5 ----- drivers/md/md.c | 3 --- drivers/scsi/scsi_lib.c | 3 +-- include/linux/blkdev.h | 9 ++++++--- 7 files changed, 13 insertions(+), 40 deletions(-) diff --git a/block/blk-merge.c b/block/blk-merge.c index 5e7dc9973458..01d85b5f93dd 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -22,7 +22,7 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q, return 0; fbio = bio; - cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); + cluster = blk_queue_cluster(q); seg_size = 0; phys_size = nr_phys_segs = 0; for_each_bio(bio) { @@ -88,7 +88,7 @@ EXPORT_SYMBOL(blk_recount_segments); static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio, struct bio *nxt) { - if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags)) + if (!blk_queue_cluster(q)) return 0; if (bio->bi_seg_back_size + nxt->bi_seg_front_size > @@ -124,7 +124,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, int nsegs, cluster; nsegs = 0; - cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); + cluster = blk_queue_cluster(q); /* * for each bio in rq diff --git a/block/blk-settings.c b/block/blk-settings.c index 3430c1fc9df7..331763a2afbd 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -108,7 +108,7 @@ void blk_set_default_limits(struct queue_limits *lim) lim->alignment_offset = 0; lim->io_opt = 0; lim->misaligned = 0; - lim->no_cluster = 0; + lim->cluster = 1; } EXPORT_SYMBOL(blk_set_default_limits); @@ -451,15 +451,6 @@ EXPORT_SYMBOL(blk_queue_io_opt); void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b) { blk_stack_limits(&t->limits, &b->limits, 0); - - if (!t->queue_lock) - WARN_ON_ONCE(1); - else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) { - unsigned long flags; - spin_lock_irqsave(t->queue_lock, flags); - queue_flag_clear(QUEUE_FLAG_CLUSTER, t); - spin_unlock_irqrestore(t->queue_lock, flags); - } } EXPORT_SYMBOL(blk_queue_stack_limits); @@ -530,7 +521,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, t->io_min = max(t->io_min, b->io_min); t->io_opt = lcm(t->io_opt, b->io_opt); - t->no_cluster |= b->no_cluster; + t->cluster &= b->cluster; t->discard_zeroes_data &= b->discard_zeroes_data; /* Physical block size a multiple of the logical block size? */ @@ -626,7 +617,6 @@ void disk_stack_limits(struct gendisk *disk, struct block_device *bdev, sector_t offset) { struct request_queue *t = disk->queue; - struct request_queue *b = bdev_get_queue(bdev); if (bdev_stack_limits(&t->limits, bdev, offset >> 9) < 0) { char top[BDEVNAME_SIZE], bottom[BDEVNAME_SIZE]; @@ -637,17 +627,6 @@ void disk_stack_limits(struct gendisk *disk, struct block_device *bdev, printk(KERN_NOTICE "%s: Warning: Device %s is misaligned\n", top, bottom); } - - if (!t->queue_lock) - WARN_ON_ONCE(1); - else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) { - unsigned long flags; - - spin_lock_irqsave(t->queue_lock, flags); - if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) - queue_flag_clear(QUEUE_FLAG_CLUSTER, t); - spin_unlock_irqrestore(t->queue_lock, flags); - } } EXPORT_SYMBOL(disk_stack_limits); diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 306759bbdf1b..d2466540488c 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -114,7 +114,7 @@ static ssize_t queue_max_segments_show(struct request_queue *q, char *page) static ssize_t queue_max_segment_size_show(struct request_queue *q, char *page) { - if (test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags)) + if (blk_queue_cluster(q)) return queue_var_show(queue_max_segment_size(q), (page)); return queue_var_show(PAGE_CACHE_SIZE, (page)); diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 9924ea23032d..4a83321c634d 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1081,11 +1081,6 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, */ q->limits = *limits; - if (limits->no_cluster) - queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q); - else - queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q); - dm_table_set_integrity(t); /* diff --git a/drivers/md/md.c b/drivers/md/md.c index ef1dae2770ca..db6552ca890c 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4248,9 +4248,6 @@ static int md_alloc(dev_t dev, char *name) goto abort; mddev->queue->queuedata = mddev; - /* Can be unlocked because the queue is new: no concurrency */ - queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, mddev->queue); - blk_queue_make_request(mddev->queue, md_make_request); disk = alloc_disk(1 << shift); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9cc450b8f942..c2a9e12fa6e1 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1640,9 +1640,8 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, blk_queue_max_segment_size(q, dma_get_max_seg_size(dev)); - /* New queue, no concurrency on queue_flags */ if (!shost->use_clustering) - queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q); + q->limits.cluster = 0; /* * set a reasonable default alignment on word boundaries: the diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 7b35803a56cc..c35de7641159 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -325,7 +325,7 @@ struct queue_limits { unsigned char misaligned; unsigned char discard_misaligned; - unsigned char no_cluster; + unsigned char cluster; signed char discard_zeroes_data; }; @@ -448,7 +448,6 @@ struct request_queue #endif }; -#define QUEUE_FLAG_CLUSTER 0 /* cluster several segments into 1 */ #define QUEUE_FLAG_QUEUED 1 /* uses generic tag queueing */ #define QUEUE_FLAG_STOPPED 2 /* queue is stopped */ #define QUEUE_FLAG_SYNCFULL 3 /* read queue has been filled */ @@ -469,7 +468,6 @@ struct request_queue #define QUEUE_FLAG_NOXMERGES 17 /* No extended merges */ #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ - (1 << QUEUE_FLAG_CLUSTER) | \ (1 << QUEUE_FLAG_STACKABLE) | \ (1 << QUEUE_FLAG_SAME_COMP)) @@ -636,6 +634,11 @@ enum { #define rq_data_dir(rq) ((rq)->cmd_flags & 1) +static inline unsigned int blk_queue_cluster(struct request_queue *q) +{ + return q->limits.cluster; +} + /* * We regard a request as sync, if either a read or a sync write */ -- cgit v1.2.3 From 7ff06f34531f702f726ab2632476fdfadfffe32c Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sat, 25 Dec 2010 19:57:41 +0100 Subject: x86/microcode: Fix double vfree() and remove redundant pointer checks before vfree() commit 5cdd2de0a76d0ac47f107c8a7b32d75d25768dc1 upstream. In arch/x86/kernel/microcode_intel.c::generic_load_microcode() we have this: while (leftover) { ... if (get_ucode_data(mc, ucode_ptr, mc_size) || microcode_sanity_check(mc) < 0) { vfree(mc); break; } ... } if (mc) vfree(mc); This will cause a double free of 'mc'. This patch fixes that by just removing the vfree() call in the loop since 'mc' will be freed nicely just after we break out of the loop. There's also a second change in the patch. I noticed a lot of checks for pointers being NULL before passing them to vfree(). That's completely redundant since vfree() deals gracefully with being passed a NULL pointer. Removing the redundant checks yields a nice size decrease for the object file. Size before the patch: text data bss dec hex filename 4578 240 1032 5850 16da arch/x86/kernel/microcode_intel.o Size after the patch: text data bss dec hex filename 4489 240 984 5713 1651 arch/x86/kernel/microcode_intel.o Signed-off-by: Jesper Juhl Acked-by: Tigran Aivazian Signed-off-by: Andi Kleen Cc: Shaohua Li LKML-Reference: Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/microcode_intel.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 356170262a93..2573689bda77 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -364,8 +364,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, /* For performance reasons, reuse mc area when possible */ if (!mc || mc_size > curr_mc_size) { - if (mc) - vfree(mc); + vfree(mc); mc = vmalloc(mc_size); if (!mc) break; @@ -374,13 +373,11 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, if (get_ucode_data(mc, ucode_ptr, mc_size) || microcode_sanity_check(mc) < 0) { - vfree(mc); break; } if (get_matching_microcode(&uci->cpu_sig, mc, new_rev)) { - if (new_mc) - vfree(new_mc); + vfree(new_mc); new_rev = mc_header.rev; new_mc = mc; mc = NULL; /* trigger new vmalloc */ @@ -390,12 +387,10 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, leftover -= mc_size; } - if (mc) - vfree(mc); + vfree(mc); if (leftover) { - if (new_mc) - vfree(new_mc); + vfree(new_mc); state = UCODE_ERROR; goto out; } @@ -405,8 +400,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, goto out; } - if (uci->mc) - vfree(uci->mc); + vfree(uci->mc); uci->mc = (struct microcode_intel *)new_mc; pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n", -- cgit v1.2.3 From 90a95aac955755dfed6025e745a7bd5688b7c4b8 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Fri, 5 Nov 2010 16:53:42 +0100 Subject: posix-cpu-timers: workaround to suppress the problems with mt exec commit e0a70217107e6f9844628120412cb27bb4cea194 upstream. posix-cpu-timers.c correctly assumes that the dying process does posix_cpu_timers_exit_group() and removes all !CPUCLOCK_PERTHREAD timers from signal->cpu_timers list. But, it also assumes that timer->it.cpu.task is always the group leader, and thus the dead ->task means the dead thread group. This is obviously not true after de_thread() changes the leader. After that almost every posix_cpu_timer_ method has problems. It is not simple to fix this bug correctly. First of all, I think that timer->it.cpu should use struct pid instead of task_struct. Also, the locking should be reworked completely. In particular, tasklist_lock should not be used at all. This all needs a lot of nontrivial and hard-to-test changes. Change __exit_signal() to do posix_cpu_timers_exit_group() when the old leader dies during exec. This is not the fix, just the temporary hack to hide the problem for 2.6.37 and stable. IOW, this is obviously wrong but this is what we currently have anyway: cpu timers do not work after mt exec. In theory this change adds another race. The exiting leader can detach the timers which were attached to the new leader. However, the window between de_thread() and release_task() is small, we can pretend that sys_timer_create() was called before de_thread(). Signed-off-by: Oleg Nesterov Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/exit.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kernel/exit.c b/kernel/exit.c index d1e6789064cf..41d44c36816f 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -94,6 +94,14 @@ static void __exit_signal(struct task_struct *tsk) tty = sig->tty; sig->tty = NULL; } else { + /* + * This can only happen if the caller is de_thread(). + * FIXME: this is the temporary hack, we should teach + * posix-cpu-timers to handle this case correctly. + */ + if (unlikely(has_group_leader_pid(tsk))) + posix_cpu_timers_exit_group(tsk); + /* * If there is any task waiting for the group exit * then notify it: -- cgit v1.2.3 From 5655b6d4e0eb834ab2fff7d6bf0820a60cfa0fdc Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 14 Dec 2010 16:16:16 -0300 Subject: gspca - sonixj: Set the flag for some devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit b2272a49e7df37732d73988f00468ce31e1ebc92 upstream. The flag PDN_INV indicates that the sensor pin S_PWR_DN has not the same value as other webcams with the same sensor. For now, only two webcams have been so detected: the Microsoft's VX1000 and VX3000. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/media/video/gspca/sonixj.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index d5754c1506f1..30720fa26b7f 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -88,6 +88,9 @@ enum { u8 jpeg_hdr[JPEG_HDR_SZ]; }; +/* device flags */ +#define PDN_INV 1 /* inverse pin S_PWR_DN / sn_xxx tables */ + /* V4L2 controls supported by the driver */ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); @@ -3004,8 +3007,8 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)}, {USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)}, #endif - {USB_DEVICE(0x045e, 0x00f5), BS(SN9C105, OV7660)}, - {USB_DEVICE(0x045e, 0x00f7), BS(SN9C105, OV7660)}, + {USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, PDN_INV)}, + {USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, PDN_INV)}, {USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)}, {USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)}, {USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)}, -- cgit v1.2.3 From cae5e948bc8775fb251f4b2286f34d027c21a0b1 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 14 Dec 2010 16:15:37 -0300 Subject: gspca - sonixj: Add a flag in the driver_info table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit c6c14330717f9850b4b4c054b81424b9979cd07d upstream. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/media/video/gspca/sonixj.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 30720fa26b7f..da2ae07a1991 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -57,6 +57,7 @@ struct sd { u8 jpegqual; /* webcam quality */ u8 reg18; + u8 flags; s8 ag_cnt; #define AG_CNT_START 13 @@ -1777,7 +1778,8 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; sd->bridge = id->driver_info >> 16; - sd->sensor = id->driver_info; + sd->sensor = id->driver_info >> 8; + sd->flags = id->driver_info; cam = &gspca_dev->cam; if (sd->sensor == SENSOR_ADCM1700) { @@ -3001,7 +3003,11 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ #define BS(bridge, sensor) \ .driver_info = (BRIDGE_ ## bridge << 16) \ - | SENSOR_ ## sensor + | (SENSOR_ ## sensor << 8) +#define BSF(bridge, sensor, flags) \ + .driver_info = (BRIDGE_ ## bridge << 16) \ + | (SENSOR_ ## sensor << 8) \ + | (flags) static const __devinitdata struct usb_device_id device_table[] = { #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)}, -- cgit v1.2.3 From f776b89f14c57f89a21110b8e78d9dafe71ae80d Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 10 Jan 2011 13:38:21 +0100 Subject: mac80211: fix hard lockup in sta_addba_resp_timer_expired Problem is 2.6.35 specific, bug was introduced in backport of upstream 44271488b91c9eecf249e075a1805dd887e222d2 commit. We can not call del_timer_sync(addba_resp_timer) from ___ieee80211_stop_tx_ba_session(), as this function can be called from that timer callback. To fix, simply use not synchronous del_timer(). Resolve https://bugzilla.redhat.com/show_bug.cgi?id=667459 Reported-and-tested-by: Mathieu Chouquet-Stringer Signed-off-by: Stanislaw Gruszka Signed-off-by: Andi Kleen --- net/mac80211/agg-tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index f935490560ba..72ab63d6a536 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -138,7 +138,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, sta->sta.addr, tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ - del_timer_sync(&tid_tx->addba_resp_timer); + del_timer(&tid_tx->addba_resp_timer); state = &sta->ampdu_mlme.tid_state_tx[tid]; -- cgit v1.2.3 From c82c51bbf2cfd71b09ca98da799f03009a6507e8 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Sat, 8 Jan 2011 01:37:26 -0800 Subject: Input: i8042 - introduce 'notimeout' blacklist for Dell Vostro V13 i8042 controller present in Dell Vostro V13 errorneously signals spurious timeouts. Introduce i8042.notimeout parameter for ignoring i8042-signalled timeouts and apply this quirk automatically for Dell Vostro V13, based on DMI match. In addition to that, this machine also needs to be added to nomux blacklist. Signed-off-by: Jiri Kosina Signed-off-by: Dmitry Torokhov Signed-off-by: Andi Kleen --- Documentation/kernel-parameters.txt | 1 + drivers/input/serio/i8042-x86ia64io.h | 21 +++++++++++++++++++++ drivers/input/serio/i8042.c | 6 +++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 2b2407d9a6d0..c74ff6f980dc 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -917,6 +917,7 @@ and is between 256 and 4096 characters. It is defined in the file controller i8042.nopnp [HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX controllers + i8042.notimeout [HW] Ignore timeout condition signalled by conroller i8042.panicblink= [HW] Frequency with which keyboard LEDs should blink when kernel panics (default is 0.5 sec) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 8c53926eb20b..a0730fdd31c4 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -420,6 +420,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), }, }, + { + /* Dell Vostro V13 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"), + }, + }, { } }; @@ -541,6 +548,17 @@ static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = { }; #endif +static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = { + { + /* Dell Vostro V13 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"), + }, + }, + { } +}; + /* * Some Wistron based laptops need us to explicitly enable the 'Dritek * keyboard extension' to make their extra keys start generating scancodes. @@ -893,6 +911,9 @@ static int __init i8042_platform_init(void) if (dmi_check_system(i8042_dmi_nomux_table)) i8042_nomux = true; + if (dmi_check_system(i8042_dmi_notimeout_table)) + i8042_notimeout = true; + if (dmi_check_system(i8042_dmi_dritek_table)) i8042_dritek = true; #endif /* CONFIG_X86 */ diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 5d42358d0da6..3e8a78fe0bde 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -65,6 +65,10 @@ static unsigned int i8042_blink_frequency = 500; module_param_named(panicblink, i8042_blink_frequency, uint, 0600); MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics"); +static bool i8042_notimeout; +module_param_named(notimeout, i8042_notimeout, bool, 0); +MODULE_PARM_DESC(notimeout, "Ignore timeouts signalled by i8042"); + #ifdef CONFIG_X86 static bool i8042_dritek; module_param_named(dritek, i8042_dritek, bool, 0); @@ -507,7 +511,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) } else { dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | - ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0); + ((str & I8042_STR_TIMEOUT && !i8042_notimeout) ? SERIO_TIMEOUT : 0); port_no = (str & I8042_STR_AUXDATA) ? I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; -- cgit v1.2.3 From be9627d438a0bbad74b10fa58cc87b9869de33e6 Mon Sep 17 00:00:00 2001 From: Steve Conklin Date: Sun, 6 Feb 2011 11:04:06 -0800 Subject: revert-drm-radeon-kms-properly-compute-group_size-on-6xx-7xx Revert drm/radeon/kms: properly compute group_size on 6xx/7xx From: Steve Conklin We discovered a regression for Radeon users in our latest proposed kernel for 2.6.35 (Maverick), and have isolated it to this patch: http://git.kernel.org/?p=linux/kernel/git/longterm/linux-2.6.35.y.git;a=commit;h=b8e9a4a45f8427837f4dba89 +bda4d4e3f3a5c726 We took that patch as part of 2.6.35.10, and one of our testers has reported that our build of that kernel also exhibits the problem. These are mainline kernels built with the Ubuntu configs. http://kernel.ubuntu.com/~kernel-ppa/mainline/v2.6.35.10-maverick/ Our bug report is here: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/703553 Upstream bug report: https://bugzilla.kernel.org/show_bug.cgi?id=24802 Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/r600.c | 7 ++----- drivers/gpu/drm/radeon/rv770.c | 9 ++++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index cdddc4d4063a..abc2a661b922 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1597,11 +1597,8 @@ void r600_gpu_init(struct radeon_device *rdev) rdev->config.r600.tiling_npipes = rdev->config.r600.max_tile_pipes; rdev->config.r600.tiling_nbanks = 4 << ((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); tiling_config |= BANK_TILING((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); - tiling_config |= GROUP_SIZE((ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); - if ((ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) - rdev->config.r600.tiling_group_size = 512; - else - rdev->config.r600.tiling_group_size = 256; + tiling_config |= GROUP_SIZE(0); + rdev->config.r600.tiling_group_size = 256; tmp = (ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT; if (tmp > 3) { tiling_config |= ROW_TILING(3); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 082c38044154..67e807371a08 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -627,11 +627,10 @@ static void rv770_gpu_init(struct radeon_device *rdev) else gb_tiling_config |= BANK_TILING((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); rdev->config.rv770.tiling_nbanks = 4 << ((gb_tiling_config >> 4) & 0x3); - gb_tiling_config |= GROUP_SIZE((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); - if ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) - rdev->config.rv770.tiling_group_size = 512; - else - rdev->config.rv770.tiling_group_size = 256; + + gb_tiling_config |= GROUP_SIZE(0); + rdev->config.rv770.tiling_group_size = 256; + if (((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT) > 3) { gb_tiling_config |= ROW_TILING(3); gb_tiling_config |= SAMPLE_SPLIT(3); -- cgit v1.2.3 From f973dacde9f9eddd6ead17532d1a5b6e45a0fc72 Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Thu, 30 Dec 2010 02:01:03 -0600 Subject: mac80211: fix mesh forwarding when ratelimited too [ upstream commit 919bbad580445801c22ef6ccbe624551fee652bd ] Commit b51aff057c9d0ef6c529dc25fd9f775faf7b6c63 said: Under memory pressure, the mac80211 mesh code may helpfully print a message that it failed to clone a mesh frame and then will proceed to crash trying to use it anyway. Fix that. Avoid the reference whenever the frame copy is unsuccessful regardless of the debug message being suppressed or printed. Cc: stable@kernel.org [2.6.27+] Signed-off-by: Milton Miller Signed-off-by: John W. Linville Signed-off-by: Andi Kleen --- net/mac80211/rx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3a39074df1d7..dc7e773c8496 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1707,11 +1707,11 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) fwd_skb = skb_copy(skb, GFP_ATOMIC); - if (!fwd_skb && net_ratelimit()) { + if (!fwd_skb && net_ratelimit()) printk(KERN_DEBUG "%s: failed to clone mesh frame\n", sdata->name); + if (!fwd_skb) goto out; - } fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); -- cgit v1.2.3 From d3fef978044748b2ebf601abe96f52863b107e47 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 18 Dec 2010 19:30:48 +0100 Subject: mac80211: fix initialization of skb->cb in ieee80211_subif_start_xmit [ upstream commit 489ee9195a7de9e6bc833d639ff6b553ffdad90e ] The change 'mac80211: Fix BUG in pskb_expand_head when transmitting shared skbs' added a check for copying the skb if it's shared, however the tx info variable still points at the cb of the old skb Signed-off-by: Felix Fietkau Acked-by: Helmut Schaa Signed-off-by: John W. Linville Signed-off-by: Andi Kleen --- net/mac80211/tx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 10910d62d8cd..1ec650bf0920 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1668,7 +1668,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_info *info; int ret = NETDEV_TX_BUSY, head_need; u16 ethertype, hdrlen, meshhdrlen = 0; __le16 fc; @@ -1956,6 +1956,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, skb_set_network_header(skb, nh_pos); skb_set_transport_header(skb, h_pos); + info = IEEE80211_SKB_CB(skb); memset(info, 0, sizeof(*info)); dev->trans_start = jiffies; -- cgit v1.2.3 From d6c90f5b218c1ddf1496045e3939b1c960c7cb9f Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sun, 6 Feb 2011 11:04:07 -0800 Subject: Release 2.6.35.11 Release 2.6.35.11 Signed-off-by: Andi Kleen --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 653850194d1b..78daa864f9fd 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 35 -EXTRAVERSION = .10 +EXTRAVERSION = .11 NAME = Yokohama # *DOCUMENTATION* -- cgit v1.2.3 From 04c0aca8ff980e0654d4b4f519cab8da7ede638e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 2 Aug 2010 18:59:28 -0300 Subject: perf session: Invalidate last_match when removing threads from rb_tree [ upstream commit 70597f21f128b7dd6a2490078bea99d704b6f8c3 ] If we receive two PERF_RECORD_EXIT for the same thread, we can end up reusing session->last_match and trying to remove the thread twice from the rb_tree, causing a segfault, so invalidade last_match in perf_session__remove_thread. Receiving two PERF_RECORD_EXIT for the same thread is a bug, but its a harmless one if we make the tool more robust, like this patch does. Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Stephane Eranian LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Andi Kleen --- tools/perf/util/session.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index c422cd676313..af094a20505d 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -134,6 +134,7 @@ void perf_session__delete(struct perf_session *self) void perf_session__remove_thread(struct perf_session *self, struct thread *th) { + self->last_match = NULL; rb_erase(&th->rb_node, &self->threads); /* * We may have references to this thread, for instance in some hist_entry -- cgit v1.2.3 From 5ab76b295a4922e7331ad846c3828d5daf709f45 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Mon, 9 Aug 2010 23:48:20 -0300 Subject: thinkpad-acpi: lock down size of hotkey keymap [ upstream commit 34a656d22f5539f613b93e7a1d14b4bd53592505 ] Use a safer coding style for the hotkey keymap. This does not fix any problems, as the current code is correct. But it might help avoid mistakes in the future. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Matthew Garrett Signed-off-by: Andi Kleen --- drivers/platform/x86/thinkpad_acpi.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 4bdb13796e24..2119179ea92c 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -1911,6 +1911,17 @@ enum { /* hot key scan codes (derived from ACPI DSDT) */ TP_ACPI_HOTKEYSCAN_VOLUMEDOWN, TP_ACPI_HOTKEYSCAN_MUTE, TP_ACPI_HOTKEYSCAN_THINKPAD, + TP_ACPI_HOTKEYSCAN_UNK1, + TP_ACPI_HOTKEYSCAN_UNK2, + TP_ACPI_HOTKEYSCAN_UNK3, + TP_ACPI_HOTKEYSCAN_UNK4, + TP_ACPI_HOTKEYSCAN_UNK5, + TP_ACPI_HOTKEYSCAN_UNK6, + TP_ACPI_HOTKEYSCAN_UNK7, + TP_ACPI_HOTKEYSCAN_UNK8, + + /* Hotkey keymap size */ + TPACPI_HOTKEY_MAP_LEN }; enum { /* Keys/events available through NVRAM polling */ @@ -3113,7 +3124,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) * If the above is too much to ask, don't change the keymap. * Ask the thinkpad-acpi maintainer to do it, instead. */ - static u16 ibm_keycode_map[] __initdata = { + static u16 ibm_keycode_map[TPACPI_HOTKEY_MAP_LEN] __initdata = { /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ KEY_FN_F1, KEY_FN_F2, KEY_COFFEE, KEY_SLEEP, KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, @@ -3147,7 +3158,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, }; - static u16 lenovo_keycode_map[] __initdata = { + static u16 lenovo_keycode_map[TPACPI_HOTKEY_MAP_LEN] __initdata = { /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ KEY_FN_F1, KEY_COFFEE, KEY_BATTERY, KEY_SLEEP, KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, @@ -3191,7 +3202,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, }; -#define TPACPI_HOTKEY_MAP_LEN ARRAY_SIZE(ibm_keycode_map) #define TPACPI_HOTKEY_MAP_SIZE sizeof(ibm_keycode_map) #define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(ibm_keycode_map[0]) @@ -3469,7 +3479,8 @@ static bool hotkey_notify_hotkey(const u32 hkey, *send_acpi_ev = true; *ignore_acpi_ev = false; - if (scancode > 0 && scancode < 0x21) { + /* HKEY event 0x1001 is scancode 0x00 */ + if (scancode > 0 && scancode <= TPACPI_HOTKEY_MAP_LEN) { scancode--; if (!(hotkey_source_mask & (1 << scancode))) { tpacpi_input_send_key_masked(scancode); -- cgit v1.2.3 From 27bfb47045fd180d635aea0ef704d591b7fd420f Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Mon, 9 Aug 2010 23:48:21 -0300 Subject: thinkpad-acpi: add support for model-specific keymaps [ upstream commit d1e14dca6a18aa40394316c872993ae3bc7e311a ] Use the quirks engine to select model-specific keymaps, which makes it much easier to extend should we need it. Keycodes are based on the tables at http://www.thinkwiki.org/wiki/Default_meanings_of_special_keys. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Matthew Garrett Signed-off-by: Andi Kleen --- drivers/platform/x86/thinkpad_acpi.c | 60 +++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 2119179ea92c..7dd7cde34d20 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3093,6 +3093,8 @@ static const struct tpacpi_quirk tpacpi_hotkey_qtable[] __initconst = { TPACPI_Q_IBM('1', 'D', TPACPI_HK_Q_INIMASK), /* X22, X23, X24 */ }; +typedef u16 tpacpi_keymap_t[TPACPI_HOTKEY_MAP_LEN]; + static int __init hotkey_init(struct ibm_init_struct *iibm) { /* Requirements for changing the default keymaps: @@ -3124,9 +3126,17 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) * If the above is too much to ask, don't change the keymap. * Ask the thinkpad-acpi maintainer to do it, instead. */ - static u16 ibm_keycode_map[TPACPI_HOTKEY_MAP_LEN] __initdata = { + + enum keymap_index { + TPACPI_KEYMAP_IBM_GENERIC = 0, + TPACPI_KEYMAP_LENOVO_GENERIC, + }; + + static const tpacpi_keymap_t tpacpi_keymaps[] __initconst = { + /* Generic keymap for IBM ThinkPads */ + [TPACPI_KEYMAP_IBM_GENERIC] = { /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ - KEY_FN_F1, KEY_FN_F2, KEY_COFFEE, KEY_SLEEP, + KEY_FN_F1, KEY_BATTERY, KEY_COFFEE, KEY_SLEEP, KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND, @@ -3157,8 +3167,10 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) /* (assignments unknown, please report if found) */ KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, - }; - static u16 lenovo_keycode_map[TPACPI_HOTKEY_MAP_LEN] __initdata = { + }, + + /* Generic keymap for Lenovo ThinkPads */ + [TPACPI_KEYMAP_LENOVO_GENERIC] = { /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ KEY_FN_F1, KEY_COFFEE, KEY_BATTERY, KEY_SLEEP, KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, @@ -3200,10 +3212,25 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) /* (assignments unknown, please report if found) */ KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, + }, }; -#define TPACPI_HOTKEY_MAP_SIZE sizeof(ibm_keycode_map) -#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(ibm_keycode_map[0]) + static const struct tpacpi_quirk tpacpi_keymap_qtable[] __initconst = { + /* Generic maps (fallback) */ + { + .vendor = PCI_VENDOR_ID_IBM, + .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY, + .quirks = TPACPI_KEYMAP_IBM_GENERIC, + }, + { + .vendor = PCI_VENDOR_ID_LENOVO, + .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY, + .quirks = TPACPI_KEYMAP_LENOVO_GENERIC, + }, + }; + +#define TPACPI_HOTKEY_MAP_SIZE sizeof(tpacpi_keymap_t) +#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(tpacpi_keymap_t[0]) int res, i; int status; @@ -3212,6 +3239,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) bool tabletsw_state = false; unsigned long quirks; + unsigned long keymap_id; vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, "initializing hotkey subdriver\n"); @@ -3352,7 +3380,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) goto err_exit; /* Set up key map */ - hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, GFP_KERNEL); if (!hotkey_keycode_map) { @@ -3362,17 +3389,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) goto err_exit; } - if (tpacpi_is_lenovo()) { - dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, - "using Lenovo default hot key map\n"); - memcpy(hotkey_keycode_map, &lenovo_keycode_map, - TPACPI_HOTKEY_MAP_SIZE); - } else { - dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, - "using IBM default hot key map\n"); - memcpy(hotkey_keycode_map, &ibm_keycode_map, - TPACPI_HOTKEY_MAP_SIZE); - } + keymap_id = tpacpi_check_quirks(tpacpi_keymap_qtable, + ARRAY_SIZE(tpacpi_keymap_qtable)); + BUG_ON(keymap_id >= ARRAY_SIZE(tpacpi_keymaps)); + dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, + "using keymap number %lu\n", keymap_id); + + memcpy(hotkey_keycode_map, &tpacpi_keymaps[keymap_id], + TPACPI_HOTKEY_MAP_SIZE); input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN); tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; -- cgit v1.2.3 From 41013dc84c7f72133d54a79c46c96bdf9c776191 Mon Sep 17 00:00:00 2001 From: Jens Taprogge Date: Mon, 9 Aug 2010 23:48:22 -0300 Subject: thinkpad-acpi: Add KEY_CAMERA (Fn-F6) for Lenovo keyboards [ upstream commit 2b75426282a8eb29d0a004ef0d289b0491c719be ] On the T410s and most likely other current models, Fn-F6 is labeled as Camera/Headphone key. Report key presses as KEY_CAMERA. Signed-off-by: Jens Taprogge Acked-by: Jerone Young Acked-by: Henrique de Moraes Holschuh Signed-off-by: Matthew Garrett Signed-off-by: Andi Kleen --- drivers/platform/x86/thinkpad_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 7dd7cde34d20..a48c80acba15 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3173,7 +3173,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) [TPACPI_KEYMAP_LENOVO_GENERIC] = { /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ KEY_FN_F1, KEY_COFFEE, KEY_BATTERY, KEY_SLEEP, - KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, + KEY_WLAN, KEY_CAMERA, KEY_SWITCHVIDEOMODE, KEY_FN_F8, KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND, /* Scan codes 0x0C to 0x1F: Other ACPI HKEY hot keys */ -- cgit v1.2.3 From c556eedc001797517011d7e68a3be5dd437a2054 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Fri, 17 Sep 2010 21:53:41 -0300 Subject: thinkpad-acpi: avoid keymap pitfall [ upstream commit fc6e756894b703952fd277a1f98a5d93e7ba847a ] Change the code so that it will use the correct size for keymap entries. Do it in a way that makes it harder to screw it up in the future. Reported-by: Jaime Velasco Juan Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Matthew Garrett Signed-off-by: Andi Kleen --- drivers/platform/x86/thinkpad_acpi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index a48c80acba15..babc4d4caf3b 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3093,7 +3093,8 @@ static const struct tpacpi_quirk tpacpi_hotkey_qtable[] __initconst = { TPACPI_Q_IBM('1', 'D', TPACPI_HK_Q_INIMASK), /* X22, X23, X24 */ }; -typedef u16 tpacpi_keymap_t[TPACPI_HOTKEY_MAP_LEN]; +typedef u16 tpacpi_keymap_entry_t; +typedef tpacpi_keymap_entry_t tpacpi_keymap_t[TPACPI_HOTKEY_MAP_LEN]; static int __init hotkey_init(struct ibm_init_struct *iibm) { @@ -3230,7 +3231,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) }; #define TPACPI_HOTKEY_MAP_SIZE sizeof(tpacpi_keymap_t) -#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(tpacpi_keymap_t[0]) +#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(tpacpi_keymap_entry_t) int res, i; int status; -- cgit v1.2.3 From 48e6b121605512d87f8da1ccd014313489c19630 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 31 Mar 2011 11:57:36 -0700 Subject: Fix cred leak in AF_NETLINK Patch cab9e9848b9a8283b0504a2d7c435a9f5ba026de to the 2.6.35.y stable tree stored a ref to the current cred struct in struct scm_cookie. This was fine with AF_UNIX as that calls scm_destroy() from its packet sending functions, but AF_NETLINK, which also uses scm_send(), does not call scm_destroy() - meaning that the copied credentials leak each time SCM data is sent over a netlink socket. This can be triggered quite simply on a Fedora 13 or 14 userspace with the 2.6.35.11 kernel (or something based off of that) by calling: #!/bin/bash for ((i=0; i<100; i++)) do su - -c /bin/true cut -d: -f1 /proc/slabinfo | grep 'cred\|key\|task_struct' cat /proc/keys | wc -l done This leaks the session key that pam_keyinit creates for 'su -', which appears in /proc/keys as being revoked (has the R flag set against it) afterward su is called. Furthermore, if CONFIG_SLAB=y, then the cred and key slab object usage counts can be viewed and seen to increase. The key slab increases by one object per loop, and this can be seen after the system has had a couple of minutes to stand after the script above has been run on it. If the system is working correctly, the key and cred counts should return to roughly what they were before. Signed-off-by: David Howells Signed-off-by: Andi Kleen --- net/netlink/af_netlink.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 54d73083cb2a..56ed59eea69c 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1330,12 +1330,16 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, return err; if (msg->msg_namelen) { - if (addr->nl_family != AF_NETLINK) - return -EINVAL; + if (addr->nl_family != AF_NETLINK) { + err = -EINVAL; + goto out; + } dst_pid = addr->nl_pid; dst_group = ffs(addr->nl_groups); - if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND)) - return -EPERM; + if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND)) { + err = -EPERM; + goto out; + } } else { dst_pid = nlk->dst_pid; dst_group = nlk->dst_group; @@ -1387,6 +1391,8 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT); out: + scm_destroy(siocb->scm); + siocb->scm = NULL; return err; } -- cgit v1.2.3 From 62d0105c0950d18f92d5c056d0ddb1ac55840c5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Mon, 13 Dec 2010 21:59:09 +0100 Subject: staging: usbip: remove double giveback of URB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7571f089d7522a95c103558faf313c7af8856ceb upstream. In the vhci_urb_dequeue() function the TCP connection is checked twice. Each time when the TCP connection is closed the URB is unlinked and given back. Remove the second attempt of unlinking and giving back of the URB completely. This patch fixes the bug described at https://bugzilla.kernel.org/show_bug.cgi?id=24872 . Signed-off-by: Márton Németh Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/usbip/vhci_hcd.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index b6c871c6d5c0..8caa1e305981 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -799,20 +799,6 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) spin_unlock_irqrestore(&vdev->priv_lock, flags2); } - - if (!vdev->ud.tcp_socket) { - /* tcp connection is closed */ - usbip_uinfo("vhci_hcd: vhci_urb_dequeue() gives back urb %p\n", - urb); - - usb_hcd_unlink_urb_from_ep(hcd, urb); - - spin_unlock_irqrestore(&the_controller->lock, flags); - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, - urb->status); - spin_lock_irqsave(&the_controller->lock, flags); - } - spin_unlock_irqrestore(&the_controller->lock, flags); usbip_dbg_vhci_hc("leave\n"); -- cgit v1.2.3 From 66d3a1d691bc17083d7fe1f7745991426e4b1245 Mon Sep 17 00:00:00 2001 From: Alex He Date: Tue, 7 Dec 2010 10:10:08 +0800 Subject: USB: EHCI: ASPM quirk of ISOC on AMD SB800 commit 05570297ecbe834b1756b522412b68eaffb9ab11 upstream. When ASPM PM Feature is enabled on UMI link, devices that use ISOC stream of data transfer may be exposed to longer latency causing less than optimal per- formance of the device. The longer latencies are normal and are due to link wake time coming out of low power state which happens frequently to save power when the link is not active. The following code will make exception for certain features of ASPM to be by passed and keep the logic normal state only when the ISOC device is connected and active. This change will allow the device to run at optimal performance yet minimize the impact on overall power savings. Signed-off-by: Alex He Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/ehci-hcd.c | 8 +++++ drivers/usb/host/ehci-pci.c | 32 ++++++++++++++++++ drivers/usb/host/ehci-sched.c | 79 +++++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/ehci.h | 1 + 4 files changed, 120 insertions(+) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index b14be9cd6f79..626731269293 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -102,6 +102,9 @@ MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) +/* for ASPM quirk of ISOC on AMD SB800 */ +static struct pci_dev *amd_nb_dev; + /*-------------------------------------------------------------------------*/ #include "ehci.h" @@ -501,6 +504,11 @@ static void ehci_stop (struct usb_hcd *hcd) spin_unlock_irq (&ehci->lock); ehci_mem_cleanup (ehci); + if (amd_nb_dev) { + pci_dev_put(amd_nb_dev); + amd_nb_dev = NULL; + } + #ifdef EHCI_STATS ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n", ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 19f5070d5c48..1851c09d2e54 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -41,6 +41,35 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) return 0; } +static int ehci_quirk_amd_SB800(struct ehci_hcd *ehci) +{ + struct pci_dev *amd_smbus_dev; + u8 rev = 0; + + amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL); + if (!amd_smbus_dev) + return 0; + + pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); + if (rev < 0x40) { + pci_dev_put(amd_smbus_dev); + amd_smbus_dev = NULL; + return 0; + } + + if (!amd_nb_dev) + amd_nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL); + if (!amd_nb_dev) + ehci_err(ehci, "QUIRK: unable to get AMD NB device\n"); + + ehci_info(ehci, "QUIRK: Enable AMD SB800 L1 fix\n"); + + pci_dev_put(amd_smbus_dev); + amd_smbus_dev = NULL; + + return 1; +} + /* called during probe() after chip reset completes */ static int ehci_pci_setup(struct usb_hcd *hcd) { @@ -99,6 +128,9 @@ static int ehci_pci_setup(struct usb_hcd *hcd) /* cache this readonly data; minimize chip reads */ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); + if (ehci_quirk_amd_SB800(ehci)) + ehci->amd_l1_fix = 1; + retval = ehci_halt(ehci); if (retval) return retval; diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 93f58e52503b..a530856ee1ba 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1586,6 +1586,63 @@ itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD); } +#define AB_REG_BAR_LOW 0xe0 +#define AB_REG_BAR_HIGH 0xe1 +#define AB_INDX(addr) ((addr) + 0x00) +#define AB_DATA(addr) ((addr) + 0x04) +#define NB_PCIE_INDX_ADDR 0xe0 +#define NB_PCIE_INDX_DATA 0xe4 +#define NB_PIF0_PWRDOWN_0 0x01100012 +#define NB_PIF0_PWRDOWN_1 0x01100013 + +static void ehci_quirk_amd_L1(struct ehci_hcd *ehci, int disable) +{ + u32 addr, addr_low, addr_high, val; + + outb_p(AB_REG_BAR_LOW, 0xcd6); + addr_low = inb_p(0xcd7); + outb_p(AB_REG_BAR_HIGH, 0xcd6); + addr_high = inb_p(0xcd7); + addr = addr_high << 8 | addr_low; + outl_p(0x30, AB_INDX(addr)); + outl_p(0x40, AB_DATA(addr)); + outl_p(0x34, AB_INDX(addr)); + val = inl_p(AB_DATA(addr)); + + if (disable) { + val &= ~0x8; + val |= (1 << 4) | (1 << 9); + } else { + val |= 0x8; + val &= ~((1 << 4) | (1 << 9)); + } + outl_p(val, AB_DATA(addr)); + + if (amd_nb_dev) { + addr = NB_PIF0_PWRDOWN_0; + pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr); + pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val); + if (disable) + val &= ~(0x3f << 7); + else + val |= 0x3f << 7; + + pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val); + + addr = NB_PIF0_PWRDOWN_1; + pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr); + pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val); + if (disable) + val &= ~(0x3f << 7); + else + val |= 0x3f << 7; + + pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val); + } + + return; +} + /* fit urb's itds into the selected schedule slot; activate as needed */ static int itd_link_urb ( @@ -1613,6 +1670,12 @@ itd_link_urb ( next_uframe >> 3, next_uframe & 0x7); stream->start = jiffies; } + + if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { + if (ehci->amd_l1_fix == 1) + ehci_quirk_amd_L1(ehci, 1); + } + ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; /* fill iTDs uframe by uframe */ @@ -1739,6 +1802,11 @@ itd_complete ( (void) disable_periodic(ehci); ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; + if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { + if (ehci->amd_l1_fix == 1) + ehci_quirk_amd_L1(ehci, 0); + } + if (unlikely(list_is_singular(&stream->td_list))) { ehci_to_hcd(ehci)->self.bandwidth_allocated -= stream->bandwidth; @@ -2026,6 +2094,12 @@ sitd_link_urb ( stream->interval, hc32_to_cpu(ehci, stream->splits)); stream->start = jiffies; } + + if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { + if (ehci->amd_l1_fix == 1) + ehci_quirk_amd_L1(ehci, 1); + } + ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; /* fill sITDs frame by frame */ @@ -2128,6 +2202,11 @@ sitd_complete ( (void) disable_periodic(ehci); ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; + if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { + if (ehci->amd_l1_fix == 1) + ehci_quirk_amd_L1(ehci, 0); + } + if (list_is_singular(&stream->td_list)) { ehci_to_hcd(ehci)->self.bandwidth_allocated -= stream->bandwidth; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 8b3d9c8f33ef..c702e4b9f2ee 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -131,6 +131,7 @@ struct ehci_hcd { /* one per controller */ unsigned need_io_watchdog:1; unsigned broken_periodic:1; unsigned fs_i_thresh:1; /* Intel iso scheduling */ + unsigned amd_l1_fix:1; /* required for usb32 quirk */ #define OHCI_CTRL_HCFS (3 << 6) -- cgit v1.2.3 From 68d6ff4e276aec35fbc068cab3e58eb3500dd476 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 25 Jan 2011 17:42:29 +0800 Subject: rt2x00: add device id for windy31 usb device commit 9c4cf6d94fb362c27a24df5223ed6e327eb7279a upstream. This patch adds the device id for the windy31 USB device to the rt73usb driver. Thanks to Ralf Flaxa for reporting this and providing testing and a sample device. Reported-by: Ralf Flaxa Tested-by: Ralf Flaxa Signed-off-by: Greg Kroah-Hartman Acked-by: Ivo van Doorn Signed-off-by: John W. Linville Signed-off-by: Andi Kleen --- drivers/net/wireless/rt2x00/rt73usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 1e99a020194a..47a795cd6ec8 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2392,6 +2392,7 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0812, 0x3101), USB_DEVICE_DATA(&rt73usb_ops) }, /* Qcom */ { USB_DEVICE(0x18e8, 0x6196), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x18e8, 0x6229), USB_DEVICE_DATA(&rt73usb_ops) }, -- cgit v1.2.3 From de754647c46436734c22c45772df377e664e919b Mon Sep 17 00:00:00 2001 From: Karsten Wiese Date: Tue, 4 Jan 2011 01:20:37 +0100 Subject: ALSA: snd-usb-us122l: Fix missing NULL checks commit cdce2db74e156fbd9a2dc3c7b246166f8b70955b upstream. Fix missing NULL checks in usb_stream_hwdep_poll() and usb_stream_hwdep_ioctl(). Wake up poll waiters before returning from usb_stream_hwdep_ioctl(). Signed-off-by: Karsten Wiese Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/usb/usx2y/us122l.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index 6ef68e42138e..084e6fc8d5bf 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -273,29 +273,26 @@ static unsigned int usb_stream_hwdep_poll(struct snd_hwdep *hw, struct file *file, poll_table *wait) { struct us122l *us122l = hw->private_data; - struct usb_stream *s = us122l->sk.s; unsigned *polled; unsigned int mask; poll_wait(file, &us122l->sk.sleep, wait); - switch (s->state) { - case usb_stream_ready: - if (us122l->first == file) - polled = &s->periods_polled; - else - polled = &us122l->second_periods_polled; - if (*polled != s->periods_done) { - *polled = s->periods_done; - mask = POLLIN | POLLOUT | POLLWRNORM; - break; + mask = POLLIN | POLLOUT | POLLWRNORM | POLLERR; + if (mutex_trylock(&us122l->mutex)) { + struct usb_stream *s = us122l->sk.s; + if (s && s->state == usb_stream_ready) { + if (us122l->first == file) + polled = &s->periods_polled; + else + polled = &us122l->second_periods_polled; + if (*polled != s->periods_done) { + *polled = s->periods_done; + mask = POLLIN | POLLOUT | POLLWRNORM; + } else + mask = 0; } - /* Fall through */ - mask = 0; - break; - default: - mask = POLLIN | POLLOUT | POLLWRNORM | POLLERR; - break; + mutex_unlock(&us122l->mutex); } return mask; } @@ -381,6 +378,7 @@ static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, { struct usb_stream_config *cfg; struct us122l *us122l = hw->private_data; + struct usb_stream *s; unsigned min_period_frames; int err = 0; bool high_speed; @@ -426,18 +424,18 @@ static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, snd_power_wait(hw->card, SNDRV_CTL_POWER_D0); mutex_lock(&us122l->mutex); + s = us122l->sk.s; if (!us122l->master) us122l->master = file; else if (us122l->master != file) { - if (memcmp(cfg, &us122l->sk.s->cfg, sizeof(*cfg))) { + if (!s || memcmp(cfg, &s->cfg, sizeof(*cfg))) { err = -EIO; goto unlock; } us122l->slave = file; } - if (!us122l->sk.s || - memcmp(cfg, &us122l->sk.s->cfg, sizeof(*cfg)) || - us122l->sk.s->state == usb_stream_xrun) { + if (!s || memcmp(cfg, &s->cfg, sizeof(*cfg)) || + s->state == usb_stream_xrun) { us122l_stop(us122l); if (!us122l_start(us122l, cfg->sample_rate, cfg->period_frames)) err = -EIO; @@ -448,6 +446,7 @@ unlock: mutex_unlock(&us122l->mutex); free: kfree(cfg); + wake_up_all(&us122l->sk.sleep); return err; } -- cgit v1.2.3 From f1ae3bdce55f3f01f0509ffd88eba64b2294bcf0 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 12 Jan 2011 21:55:09 +0100 Subject: hwmon: (via686a) Initialize fan_div values commit f790674d3f87df6390828ac21a7d1530f71b59c8 upstream. Functions set_fan_min() and set_fan_div() assume that the fan_div values have already been read from the register. The driver currently doesn't initialize them at load time, they are only set when function via686a_update_device() is called. This means that set_fan_min() and set_fan_div() misbehave if, for example, "sensors -s" is called before any monitoring application (e.g. "sensors") is has been run. Fix the problem by always initializing the fan_div values at device bind time. Signed-off-by: Jean Delvare Acked-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/hwmon/via686a.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index f397ce7ad598..b2074e3ba2f1 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c @@ -687,6 +687,13 @@ static int __devexit via686a_remove(struct platform_device *pdev) return 0; } +static void via686a_update_fan_div(struct via686a_data *data) +{ + int reg = via686a_read_value(data, VIA686A_REG_FANDIV); + data->fan_div[0] = (reg >> 4) & 0x03; + data->fan_div[1] = reg >> 6; +} + static void __devinit via686a_init_device(struct via686a_data *data) { u8 reg; @@ -700,6 +707,9 @@ static void __devinit via686a_init_device(struct via686a_data *data) via686a_write_value(data, VIA686A_REG_TEMP_MODE, (reg & ~VIA686A_TEMP_MODE_MASK) | VIA686A_TEMP_MODE_CONTINUOUS); + + /* Pre-read fan clock divisor values */ + via686a_update_fan_div(data); } static struct via686a_data *via686a_update_device(struct device *dev) @@ -751,9 +761,7 @@ static struct via686a_data *via686a_update_device(struct device *dev) (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) & 0xc0) >> 6; - i = via686a_read_value(data, VIA686A_REG_FANDIV); - data->fan_div[0] = (i >> 4) & 0x03; - data->fan_div[1] = i >> 6; + via686a_update_fan_div(data); data->alarms = via686a_read_value(data, VIA686A_REG_ALARM1) | -- cgit v1.2.3 From ee3c0087cd62cd7dd83410726c18bbec3803c8dc Mon Sep 17 00:00:00 2001 From: Libor Pechacek Date: Fri, 14 Jan 2011 14:30:21 +0100 Subject: USB: serial: handle Data Carrier Detect changes commit d14fc1a74e846d7851f24fc9519fe87dc12a1231 upstream. Alan's commit 335f8514f200e63d689113d29cb7253a5c282967 introduced .carrier_raised function in several drivers. That also means tty_port_block_til_ready can now suspend the process trying to open the serial port when Carrier Detect is low and put it into tty_port.open_wait queue. We need to wake up the process when Carrier Detect goes high and trigger TTY hangup when CD goes low. Some of the devices do not report modem status line changes, or at least we don't understand the status message, so for those we remove .carrier_raised again. Signed-off-by: Libor Pechacek Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/ch341.c | 10 ++++++++++ drivers/usb/serial/cp210x.c | 11 ----------- drivers/usb/serial/digi_acceleport.c | 10 ---------- drivers/usb/serial/generic.c | 20 ++++++++++++++++++++ drivers/usb/serial/keyspan_pda.c | 17 ----------------- drivers/usb/serial/pl2303.c | 11 +++++++++++ drivers/usb/serial/spcp8x5.c | 5 ++++- include/linux/usb/serial.h | 3 +++ 8 files changed, 48 insertions(+), 39 deletions(-) diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 63f7cc45bcac..7b8815ddf368 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -486,12 +486,22 @@ static void ch341_read_int_callback(struct urb *urb) if (actual_length >= 4) { struct ch341_private *priv = usb_get_serial_port_data(port); unsigned long flags; + u8 prev_line_status = priv->line_status; spin_lock_irqsave(&priv->lock, flags); priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT; if ((data[1] & CH341_MULT_STAT)) priv->multi_status_change = 1; spin_unlock_irqrestore(&priv->lock, flags); + + if ((priv->line_status ^ prev_line_status) & CH341_BIT_DCD) { + struct tty_struct *tty = tty_port_tty_get(&port->port); + if (tty) + usb_serial_handle_dcd_change(port, tty, + priv->line_status & CH341_BIT_DCD); + tty_kref_put(tty); + } + wake_up_interruptible(&priv->delta_msr_wait); } diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 9927bca29b3a..9fa3cde25641 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -49,7 +49,6 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *, static void cp210x_break_ctl(struct tty_struct *, int); static int cp210x_startup(struct usb_serial *); static void cp210x_dtr_rts(struct usb_serial_port *p, int on); -static int cp210x_carrier_raised(struct usb_serial_port *p); static int debug; @@ -165,7 +164,6 @@ static struct usb_serial_driver cp210x_device = { .tiocmset = cp210x_tiocmset, .attach = cp210x_startup, .dtr_rts = cp210x_dtr_rts, - .carrier_raised = cp210x_carrier_raised }; /* Config request types */ @@ -764,15 +762,6 @@ static int cp210x_tiocmget (struct tty_struct *tty, struct file *file) return result; } -static int cp210x_carrier_raised(struct usb_serial_port *p) -{ - unsigned int control; - cp210x_get_config(p, CP210X_GET_MDMSTS, &control, 1); - if (control & CONTROL_DCD) - return 1; - return 0; -} - static void cp210x_break_ctl (struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index fd35f73b5721..0c366952f98c 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -455,7 +455,6 @@ static int digi_write_room(struct tty_struct *tty); static int digi_chars_in_buffer(struct tty_struct *tty); static int digi_open(struct tty_struct *tty, struct usb_serial_port *port); static void digi_close(struct usb_serial_port *port); -static int digi_carrier_raised(struct usb_serial_port *port); static void digi_dtr_rts(struct usb_serial_port *port, int on); static int digi_startup_device(struct usb_serial *serial); static int digi_startup(struct usb_serial *serial); @@ -511,7 +510,6 @@ static struct usb_serial_driver digi_acceleport_2_device = { .open = digi_open, .close = digi_close, .dtr_rts = digi_dtr_rts, - .carrier_raised = digi_carrier_raised, .write = digi_write, .write_room = digi_write_room, .write_bulk_callback = digi_write_bulk_callback, @@ -1337,14 +1335,6 @@ static void digi_dtr_rts(struct usb_serial_port *port, int on) digi_set_modem_signals(port, on * (TIOCM_DTR|TIOCM_RTS), 1); } -static int digi_carrier_raised(struct usb_serial_port *port) -{ - struct digi_port *priv = usb_get_serial_port_data(port); - if (priv->dp_modem_signals & TIOCM_CD) - return 1; - return 0; -} - static int digi_open(struct tty_struct *tty, struct usb_serial_port *port) { int ret; diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index ca92f67747cc..d2d550549038 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -481,6 +481,26 @@ int usb_serial_handle_break(struct usb_serial_port *port) } EXPORT_SYMBOL_GPL(usb_serial_handle_break); +/** + * usb_serial_handle_dcd_change - handle a change of carrier detect state + * @port: usb_serial_port structure for the open port + * @tty: tty_struct structure for the port + * @status: new carrier detect status, nonzero if active + */ +void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port, + struct tty_struct *tty, unsigned int status) +{ + struct tty_port *port = &usb_port->port; + + dbg("%s - port %d, status %d", __func__, usb_port->number, status); + + if (status) + wake_up_interruptible(&port->open_wait); + else if (tty && !C_CLOCAL(tty)) + tty_hangup(tty); +} +EXPORT_SYMBOL_GPL(usb_serial_handle_dcd_change); + int usb_serial_generic_resume(struct usb_serial *serial) { struct usb_serial_port *port; diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 185fe9a7d4e0..2cbd661a92f7 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -680,22 +680,6 @@ static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on) } } -static int keyspan_pda_carrier_raised(struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - unsigned char modembits; - - /* If we can read the modem status and the DCD is low then - carrier is not raised yet */ - if (keyspan_pda_get_modem_info(serial, &modembits) >= 0) { - if (!(modembits & (1>>6))) - return 0; - } - /* Carrier raised, or we failed (eg disconnected) so - progress accordingly */ - return 1; -} - static int keyspan_pda_open(struct tty_struct *tty, struct usb_serial_port *port) @@ -882,7 +866,6 @@ static struct usb_serial_driver keyspan_pda_device = { .id_table = id_table_std, .num_ports = 1, .dtr_rts = keyspan_pda_dtr_rts, - .carrier_raised = keyspan_pda_carrier_raised, .open = keyspan_pda_open, .close = keyspan_pda_close, .write = keyspan_pda_write, diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index c98f0fb675ba..3d619e4086df 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -677,9 +677,11 @@ static void pl2303_update_line_status(struct usb_serial_port *port, { struct pl2303_private *priv = usb_get_serial_port_data(port); + struct tty_struct *tty; unsigned long flags; u8 status_idx = UART_STATE; u8 length = UART_STATE + 1; + u8 prev_line_status; u16 idv, idp; idv = le16_to_cpu(port->serial->dev->descriptor.idVendor); @@ -701,11 +703,20 @@ static void pl2303_update_line_status(struct usb_serial_port *port, /* Save off the uart status for others to look at */ spin_lock_irqsave(&priv->lock, flags); + prev_line_status = priv->line_status; priv->line_status = data[status_idx]; spin_unlock_irqrestore(&priv->lock, flags); if (priv->line_status & UART_BREAK_ERROR) usb_serial_handle_break(port); wake_up_interruptible(&priv->delta_msr_wait); + + tty = tty_port_tty_get(&port->port); + if (!tty) + return; + if ((priv->line_status ^ prev_line_status) & UART_DCD) + usb_serial_handle_dcd_change(port, tty, + priv->line_status & UART_DCD); + tty_kref_put(tty); } static void pl2303_read_int_callback(struct urb *urb) diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 329d311a35d9..b9575c805108 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -133,7 +133,7 @@ struct spcp8x5_usb_ctrl_arg { /* how come ??? */ #define UART_STATE 0x08 -#define UART_STATE_TRANSIENT_MASK 0x74 +#define UART_STATE_TRANSIENT_MASK 0x75 #define UART_DCD 0x01 #define UART_DSR 0x02 #define UART_BREAK_ERROR 0x04 @@ -531,6 +531,9 @@ static void spcp8x5_process_read_urb(struct urb *urb) tty_insert_flip_string_fixed_flag(tty, data, tty_flag, urb->actual_length); tty_flip_buffer_push(tty); + if (status & UART_DCD) + usb_serial_handle_dcd_change(port, tty, + priv->line_status & MSR_STATUS_LINE_DCD); tty_kref_put(tty); } diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 84a4c44c208b..8ab6142be3f7 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -346,6 +346,9 @@ extern int usb_serial_handle_sysrq_char(struct tty_struct *tty, struct usb_serial_port *port, unsigned int ch); extern int usb_serial_handle_break(struct usb_serial_port *port); +extern void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port, + struct tty_struct *tty, + unsigned int status); extern int usb_serial_bus_register(struct usb_serial_driver *device); -- cgit v1.2.3 From 766172f1fcb9f1c9d3556a9ecf3ba69db5c21e3f Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Sun, 2 Jan 2011 21:51:46 +0000 Subject: USB: CP210x Add two device IDs commit faea63f7ccfddfb8fc19798799fcd38c58415172 upstream. Device Ids added for IRZ Automation Teleport SG-10 GSM/GPRS Modem and DekTec DTA Plus VHF/UHF Booster/Attenuator. Signed-off-by: Craig Shelley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/cp210x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 9fa3cde25641..a77173baabe2 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -108,7 +108,9 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ { USB_DEVICE(0x10C4, 0x8382) }, /* Cygnal Integrated Products, Inc. */ { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ + { USB_DEVICE(0x10C4, 0x83D8) }, /* DekTec DTA Plus VHF/UHF Booster/Attenuator */ { USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */ + { USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */ { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ { USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ -- cgit v1.2.3 From bb7404dd6a00288acdceee180323c1857fdba236 Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Sun, 2 Jan 2011 21:59:08 +0000 Subject: USB: CP210x Removed incorrect device ID commit 9926c0df7b31b2128eebe92e0e2b052f380ea464 upstream. Device ID removed 0x10C4/0x8149 for West Mountain Radio Computerized Battery Analyzer. This device is actually based on a SiLabs C8051Fxxx, see http://www.etheus.net/SiUSBXp_Linux_Driver for further info. Signed-off-by: Craig Shelley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/cp210x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index a77173baabe2..1a85938ff0e5 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -85,7 +85,6 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */ { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ { USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */ - { USB_DEVICE(0x10C4, 0x8149) }, /* West Mountain Radio Computerized Battery Analyzer */ { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */ -- cgit v1.2.3 From 1aa5150d1ec0493d13261d98e93cac0df349896f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sch=C3=BCtz?= Date: Sun, 19 Dec 2010 21:18:38 +0100 Subject: USB: usb-storage: unusual_devs update for Cypress ATACB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit cae41118f50ef0c431e13159df6d7dd8bbd54004 upstream. New device ID added for unusual Cypress ATACB device. Signed-off-by: Richard Schütz Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/storage/unusual_cypress.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h index 44be6d75dab6..fba2824085b4 100644 --- a/drivers/usb/storage/unusual_cypress.h +++ b/drivers/usb/storage/unusual_cypress.h @@ -31,4 +31,9 @@ UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999, "Cypress ISD-300LP", US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0), +UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x9999, + "Super Top", + "USB 2.0 SATA BRIDGE", + US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0), + #endif /* defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || ... */ -- cgit v1.2.3 From b4db5d1e8095a9369bc256407a9a11a863b89248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sch=C3=BCtz?= Date: Wed, 22 Dec 2010 14:28:56 +0100 Subject: USB: usb-storage: unusual_devs update for TrekStor DataStation maxi g.u external hard drive enclosure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7e1e7bd9dbd469267b6e6de1bf8d71a7d65ce86a upstream. The TrekStor DataStation maxi g.u external hard drive enclosure uses a JMicron USB to SATA chip which needs the US_FL_IGNORE_RESIDUE flag to work properly. Signed-off-by: Richard Schütz Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/storage/unusual_devs.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index b51b121ae825..c00d52256c46 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1866,6 +1866,15 @@ UNUSUAL_DEV( 0x1908, 0x1320, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_BAD_SENSE ), +/* Patch by Richard Schtz + * This external hard drive enclosure uses a JMicron chip which + * needs the US_FL_IGNORE_RESIDUE flag to work properly. */ +UNUSUAL_DEV( 0x1e68, 0x001b, 0x0000, 0x0000, + "TrekStor GmbH & Co. KG", + "DataStation maxi g.u", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ), + UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001, "ST", "2A", -- cgit v1.2.3 From 1c710dfa6f5670d916e396f2b74aa3731f1f3ad5 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 3 Jan 2011 16:47:49 -0500 Subject: USB: usb-storage: unusual_devs entry for CamSport Evo commit 12f68c480c7155a66bd2a76ab2fef28dd5f93fa2 upstream. This patch (as1438) adds an unusual_devs entry for the MagicPixel FW_Omega2 chip, used in the CamSport Evo camera. The firmware incorrectly reports a vendor-specific bDeviceClass. Signed-off-by: Alan Stern Signed-off-by: Andi Kleen Reported-by: Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index c00d52256c46..687a41e67c13 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1043,6 +1043,15 @@ UNUSUAL_DEV( 0x084d, 0x0011, 0x0110, 0x0110, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_BULK32), +/* Reported by + * The device reports a vendor-specific device class, requiring an + * explicit vendor/product match. + */ +UNUSUAL_DEV( 0x0851, 0x1542, 0x0002, 0x0002, + "MagicPixel", + "FW_Omega2", + US_SC_DEVICE, US_PR_DEVICE, NULL, 0), + /* Andrew Lunn * PanDigital Digital Picture Frame. Does not like ALLOW_MEDIUM_REMOVAL * on LUN 4. -- cgit v1.2.3 From 2768003781dc1ce04813a56c186b3b28b4357724 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 25 Jan 2011 13:07:04 -0500 Subject: USB: usb-storage: unusual_devs entry for Coby MP3 player commit 3ea3c9b5a8464ec8223125f95e5dddb3bfd02a39 upstream. This patch (as1444) adds an unusual_devs entry for an MP3 player from Coby electronics. The device has two nasty bugs. Signed-off-by: Alan Stern Signed-off-by: Andi Kleen Tested-by: Jasper Mackenzie Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 687a41e67c13..bc437a8460b5 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1884,6 +1884,13 @@ UNUSUAL_DEV( 0x1e68, 0x001b, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ), +/* Reported by Jasper Mackenzie */ +UNUSUAL_DEV( 0x1e74, 0x4621, 0x0000, 0x0000, + "Coby Electronics", + "MP3 Player", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_BULK_IGNORE_TAG | US_FL_MAX_SECTORS_64 ), + UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001, "ST", "2A", -- cgit v1.2.3 From 1bb27e3ab6d7db2c8c82e00f55067b052f5a851e Mon Sep 17 00:00:00 2001 From: Pieter Maes Date: Tue, 18 Jan 2011 00:26:16 +0100 Subject: USB: serial: Updated support for ICOM devices commit a9d61bc49188e32d2ae9cf0f683cde3e1744feef upstream. I found the original patch on the db0fhn repeater wiki (couldn't find the email of the origial author) I guess it was never commited. I updated and added some Icom HAM-radio devices to the ftdi driver. Added extra comments to make clear what devices it are. Signed-off-by: Pieter Maes Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/ftdi_sio.c | 12 +++++++++++- drivers/usb/serial/ftdi_sio_ids.h | 22 +++++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 506d744fd72e..da67c3bb6100 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -675,7 +675,17 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, - { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C2_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2D_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2VT_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2VR_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVT_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVR_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVT_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVR_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 77ace17fd143..a2bb959059aa 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -569,11 +569,23 @@ #define OCT_US101_PID 0x0421 /* OCT US101 USB to RS-232 */ /* - * Icom ID-1 digital transceiver - */ - -#define ICOM_ID1_VID 0x0C26 -#define ICOM_ID1_PID 0x0004 + * Definitions for Icom Inc. devices + */ +#define ICOM_VID 0x0C26 /* Icom vendor ID */ +/* Note: ID-1 is a communications tranceiver for HAM-radio operators */ +#define ICOM_ID_1_PID 0x0004 /* ID-1 USB to RS-232 */ +/* Note: OPC is an Optional cable to connect an Icom Tranceiver */ +#define ICOM_OPC_U_UC_PID 0x0018 /* OPC-478UC, OPC-1122U cloning cable */ +/* Note: ID-RP* devices are Icom Repeater Devices for HAM-radio */ +#define ICOM_ID_RP2C1_PID 0x0009 /* ID-RP2C Asset 1 to RS-232 */ +#define ICOM_ID_RP2C2_PID 0x000A /* ID-RP2C Asset 2 to RS-232 */ +#define ICOM_ID_RP2D_PID 0x000B /* ID-RP2D configuration port*/ +#define ICOM_ID_RP2VT_PID 0x000C /* ID-RP2V Transmit config port */ +#define ICOM_ID_RP2VR_PID 0x000D /* ID-RP2V Receive config port */ +#define ICOM_ID_RP4KVT_PID 0x0010 /* ID-RP4000V Transmit config port */ +#define ICOM_ID_RP4KVR_PID 0x0011 /* ID-RP4000V Receive config port */ +#define ICOM_ID_RP2KVT_PID 0x0012 /* ID-RP2000V Transmit config port */ +#define ICOM_ID_RP2KVR_PID 0x0013 /* ID-RP2000V Receive config port */ /* * GN Otometrics (http://www.otometrics.com) -- cgit v1.2.3 From c7b6be3f203b079eb747e1154c88c7da92cbbbc3 Mon Sep 17 00:00:00 2001 From: Nicolaus Colberg Date: Wed, 12 Jan 2011 16:30:03 +0100 Subject: USB: adding USB support for Cinterion's HC2x, EU3 and PH8 products commit aa52b3a92918039b273fc9d1994bd34227c40269 upstream. /drivers/usb/serial/option.c: Adding support for Cinterion's HC25, HC28, HC28J, EU3-E, EU3-P and PH8 by correcting/adding Cinterion's and Siemens' Vendor IDs as well as Product IDs and USB_DEVICE tuples Signed-off-by: Nicolaus Colberg Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/option.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ba23c21759ca..a0f46c484c68 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -362,7 +362,16 @@ static void option_instat_callback(struct urb *urb); #define HAIER_VENDOR_ID 0x201e #define HAIER_PRODUCT_CE100 0x2009 -#define CINTERION_VENDOR_ID 0x0681 +/* Cinterion (formerly Siemens) products */ +#define SIEMENS_VENDOR_ID 0x0681 +#define CINTERION_VENDOR_ID 0x1e2d +#define CINTERION_PRODUCT_HC25_MDM 0x0047 +#define CINTERION_PRODUCT_HC25_MDMNET 0x0040 +#define CINTERION_PRODUCT_HC28_MDM 0x004C +#define CINTERION_PRODUCT_HC28_MDMNET 0x004A /* same for HC28J */ +#define CINTERION_PRODUCT_EU3_E 0x0051 +#define CINTERION_PRODUCT_EU3_P 0x0052 +#define CINTERION_PRODUCT_PH8 0x0053 /* Olivetti products */ #define OLIVETTI_VENDOR_ID 0x0b3c @@ -912,7 +921,17 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F) }, { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)}, { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)}, - { USB_DEVICE(CINTERION_VENDOR_ID, 0x0047) }, + /* Cinterion */ + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) }, + { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) }, + { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDMNET) }, + { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, /* HC28 enumerates with Siemens or Cinterion VID depending on FW revision */ + { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) }, + { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */ { } /* Terminating entry */ -- cgit v1.2.3 From eaeca4a0480ed6bc3f3a5af1478e7b56458f05ae Mon Sep 17 00:00:00 2001 From: Alex He Date: Tue, 21 Dec 2010 17:45:46 +0800 Subject: USB: EHCI: ASPM quirk of ISOC on AMD Hudson commit baab93afc2844b68d57b0dcca5e1d34c5d7cf411 upstream. AMD Hudson also needs the same ASPM quirk as SB800 Signed-off-by: Alex He Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/ehci-pci.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 1851c09d2e54..e9dc13693a78 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -41,28 +41,35 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) return 0; } -static int ehci_quirk_amd_SB800(struct ehci_hcd *ehci) +static int ehci_quirk_amd_hudson(struct ehci_hcd *ehci) { struct pci_dev *amd_smbus_dev; u8 rev = 0; amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL); - if (!amd_smbus_dev) - return 0; - - pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); - if (rev < 0x40) { - pci_dev_put(amd_smbus_dev); - amd_smbus_dev = NULL; - return 0; + if (amd_smbus_dev) { + pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); + if (rev < 0x40) { + pci_dev_put(amd_smbus_dev); + amd_smbus_dev = NULL; + return 0; + } + } else { + amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x780b, NULL); + if (!amd_smbus_dev) + return 0; + pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); + if (rev < 0x11 || rev > 0x18) { + pci_dev_put(amd_smbus_dev); + amd_smbus_dev = NULL; + return 0; + } } if (!amd_nb_dev) amd_nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL); - if (!amd_nb_dev) - ehci_err(ehci, "QUIRK: unable to get AMD NB device\n"); - ehci_info(ehci, "QUIRK: Enable AMD SB800 L1 fix\n"); + ehci_info(ehci, "QUIRK: Enable exception for AMD Hudson ASPM\n"); pci_dev_put(amd_smbus_dev); amd_smbus_dev = NULL; @@ -128,7 +135,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) /* cache this readonly data; minimize chip reads */ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - if (ehci_quirk_amd_SB800(ehci)) + if (ehci_quirk_amd_hudson(ehci)) ehci->amd_l1_fix = 1; retval = ehci_halt(ehci); -- cgit v1.2.3 From 58433a68ee1e403c9cf79ba15b3fca93f09b346b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 6 Jan 2011 10:17:09 -0500 Subject: USB: EHCI: fix DMA deallocation bug commit f75593ceaa08e6d27aec1a5de31cded19e850dd1 upstream. This patch (as1440) fixes a bug in ehci-hcd. ehci->periodic_size is used to compute the size in a dma_alloc_coherent() call, but then it gets changed later on. As a result, the corresponding call to dma_free_coherent() passes a different size from the original allocation. Fix the problem by adjusting ehci->periodic_size before carrying out any of the memory allocations. Signed-off-by: Alan Stern Signed-off-by: Andi Kleen Tested-by: Larry Finger CC: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 626731269293..761bbb36e494 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -544,6 +544,8 @@ static int ehci_init(struct usb_hcd *hcd) ehci->iaa_watchdog.function = ehci_iaa_watchdog; ehci->iaa_watchdog.data = (unsigned long) ehci; + hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); + /* * hw default: 1K periodic list heads, one per frame. * periodic_size can shrink by USBCMD update if hcc_params allows. @@ -551,11 +553,20 @@ static int ehci_init(struct usb_hcd *hcd) ehci->periodic_size = DEFAULT_I_TDPS; INIT_LIST_HEAD(&ehci->cached_itd_list); INIT_LIST_HEAD(&ehci->cached_sitd_list); + + if (HCC_PGM_FRAMELISTLEN(hcc_params)) { + /* periodic schedule size can be smaller than default */ + switch (EHCI_TUNE_FLS) { + case 0: ehci->periodic_size = 1024; break; + case 1: ehci->periodic_size = 512; break; + case 2: ehci->periodic_size = 256; break; + default: BUG(); + } + } if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0) return retval; /* controllers may cache some of the periodic schedule ... */ - hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); if (HCC_ISOC_CACHE(hcc_params)) // full frame cache ehci->i_thresh = 2 + 8; else // N microframes cached @@ -604,12 +615,6 @@ static int ehci_init(struct usb_hcd *hcd) /* periodic schedule size can be smaller than default */ temp &= ~(3 << 2); temp |= (EHCI_TUNE_FLS << 2); - switch (EHCI_TUNE_FLS) { - case 0: ehci->periodic_size = 1024; break; - case 1: ehci->periodic_size = 512; break; - case 2: ehci->periodic_size = 256; break; - default: BUG(); - } } ehci->command = temp; -- cgit v1.2.3 From 1569eab1b3b913d846145e3d90a40c234b3e5078 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 10 Jan 2011 11:24:14 -0500 Subject: USB: g_printer: fix bug in module parameter definitions commit ad84e4a9efb7c8ed322bafb6ebdb9c3a49a3d3a8 upstream. This patch (as1442) fixes a bug in g_printer: Module parameters should not be marked "__initdata" if they are accessible in sysfs (i.e., if the mode value in the module_param() macro is nonzero). Otherwise attempts to access the parameters will cause addressing violations. Character-string module parameters must not be marked "__initdata" if the module can be unloaded, because the kernel needs to access the parameter variable at unload time in order to free the dynamically-allocated string. Signed-off-by: Alan Stern Signed-off-by: Andi Kleen CC: Roland Kletzing CC: Craig W. Nadler Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/printer.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 4c3ac5c42237..d615eee0cc19 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -130,31 +130,31 @@ static struct printer_dev usb_printer_gadget; * parameters are in UTF-8 (superset of ASCII's 7 bit characters). */ -static ushort __initdata idVendor; +static ushort idVendor; module_param(idVendor, ushort, S_IRUGO); MODULE_PARM_DESC(idVendor, "USB Vendor ID"); -static ushort __initdata idProduct; +static ushort idProduct; module_param(idProduct, ushort, S_IRUGO); MODULE_PARM_DESC(idProduct, "USB Product ID"); -static ushort __initdata bcdDevice; +static ushort bcdDevice; module_param(bcdDevice, ushort, S_IRUGO); MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); -static char *__initdata iManufacturer; +static char *iManufacturer; module_param(iManufacturer, charp, S_IRUGO); MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); -static char *__initdata iProduct; +static char *iProduct; module_param(iProduct, charp, S_IRUGO); MODULE_PARM_DESC(iProduct, "USB Product string"); -static char *__initdata iSerialNum; +static char *iSerialNum; module_param(iSerialNum, charp, S_IRUGO); MODULE_PARM_DESC(iSerialNum, "1"); -static char *__initdata iPNPstring; +static char *iPNPstring; module_param(iPNPstring, charp, S_IRUGO); MODULE_PARM_DESC(iPNPstring, "MFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;"); -- cgit v1.2.3 From 2486a6e5f8fc141f66213999bfcc1283847c56aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 17 Jan 2011 14:19:37 +0100 Subject: USB: io_edgeport: fix the reported firmware major and minor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 271c1150b4f8e1685e5a8cbf76e329ec894481da upstream. The major and minor number saved in the product_info structure were copied from the address instead of the data, causing an inconsistency in the reported versions during firmware loading: usb 4-1: firmware: requesting edgeport/down.fw /usr/src/linux/drivers/usb/serial/io_edgeport.c: downloading firmware version (930) 1.16.4 [..] /usr/src/linux/drivers/usb/serial/io_edgeport.c: edge_startup - time 3 4328191260 /usr/src/linux/drivers/usb/serial/io_edgeport.c: FirmwareMajorVersion 0.0.4 This can cause some confusion whether firmware loaded successfully or not. Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/io_edgeport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 76e6fb3aab7a..db0e3fe4acf5 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -2894,8 +2894,8 @@ static void load_application_firmware(struct edgeport_serial *edge_serial) dbg("%s %d.%d.%d", fw_info, rec->data[0], rec->data[1], build); - edge_serial->product_info.FirmwareMajorVersion = fw->data[0]; - edge_serial->product_info.FirmwareMinorVersion = fw->data[1]; + edge_serial->product_info.FirmwareMajorVersion = rec->data[0]; + edge_serial->product_info.FirmwareMinorVersion = rec->data[1]; edge_serial->product_info.FirmwareBuildNumber = cpu_to_le16(build); for (rec = ihex_next_binrec(rec); rec; -- cgit v1.2.3 From 9c816d50bf4cf75e13a44233cf38cb54215ab976 Mon Sep 17 00:00:00 2001 From: Ionut Nicu Date: Tue, 28 Dec 2010 22:21:08 +0200 Subject: USB: ti_usb: fix module removal commit b14de3857227cd978f515247853fd15cc2425d3e upstream. If usb_deregister() is called after usb_serial_deregister() when the device is plugged in, the following Oops occurs: [ 95.337377] BUG: unable to handle kernel NULL pointer dereference at 00000010 [ 95.338236] IP: [] klist_put+0x12/0x62 [ 95.338356] *pdpt = 000000003001a001 *pde = 0000000000000000 [ 95.338356] Oops: 0000 [#1] SMP [ 95.340499] last sysfs file: /sys/devices/pci0000:00/0000:00:1d.2/usb8/idVendor [ 95.340499] Modules linked in: ti_usb_3410_5052(-) usbserial cpufreq_ondemand acpi_cpufreq mperf iptable_nat nf_nat iptable_mangle ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 ip6table_filter ip6_tables ipv6 uinput arc4 ecb iwlagn iwlcore mac80211 cfg80211 microcode pcspkr acer_wmi joydev wmi sky2 [last unloaded: scsi_wait_scan] [ 95.341908] [ 95.341908] Pid: 1532, comm: modprobe Not tainted 2.6.37-rc7+ #6 Eiger /Aspire 5930 [ 95.341908] EIP: 0060:[] EFLAGS: 00010246 CPU: 0 [ 95.341908] EIP is at klist_put+0x12/0x62 [ 95.341908] EAX: 00000000 EBX: eedc0c84 ECX: c09c21b4 EDX: 00000001 [ 95.341908] ESI: 00000000 EDI: efaa0c1c EBP: f214fe2c ESP: f214fe1c [ 95.341908] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [ 95.341908] Process modprobe (pid: 1532, ti=f214e000 task=efaaf080 task.ti=f214e000) [ 95.341908] Stack: [ 95.341908] f214fe24 eedc0c84 efaaf080 efaa0c1c f214fe34 c0776ba8 f214fe5c c0776c76 [ 95.341908] c09c21b4 c09c21b4 eedc0c84 efaaf080 00000000 c0634398 eafe2d1c f7b515f0 [ 95.341908] f214fe6c c0631b5c eafe2d50 eafe2d1c f214fe7c c0631ba2 eafe2d1c eafe2c00 [ 95.341908] Call Trace: [ 95.341908] [] ? klist_del+0xd/0xf [ 95.341908] [] ? klist_remove+0x48/0x74 [ 95.341908] [] ? devres_release_all+0x49/0x51 [ 95.341908] [] ? __device_release_driver+0x7b/0xa4 [ 95.341908] [] ? device_release_driver+0x1d/0x28 [ 95.341908] [] ? bus_remove_device+0x92/0xa1 [ 95.341908] [] ? device_del+0xf9/0x13e [ 95.341908] [] ? usb_serial_disconnect+0xd9/0x116 [usbserial] [ 95.341908] [] ? usb_disable_interface+0x32/0x40 [ 95.341908] [] ? usb_unbind_interface+0x48/0xfd [ 95.341908] [] ? __device_release_driver+0x62/0xa4 [ 95.341908] [] ? driver_detach+0x62/0x81 [ 95.341908] [] ? bus_remove_driver+0x8f/0xae [ 95.341908] [] ? driver_unregister+0x50/0x57 [ 95.341908] [] ? usb_deregister+0x77/0x84 [ 95.341908] [] ? ti_exit+0x26/0x28 [ti_usb_3410_5052] [ 95.341908] [] ? sys_delete_module+0x181/0x1de [ 95.341908] [] ? path_put+0x1a/0x1d [ 95.341908] [] ? audit_syscall_entry+0x116/0x138 [ 95.341908] [] ? sysenter_do_call+0x12/0x28 [ 95.341908] Code: 00 83 7d f0 00 74 09 85 f6 74 05 89 f0 ff 55 f0 8b 43 04 5a 5b 5e 5f 5d c3 55 89 e5 57 56 53 89 c3 83 ec 04 8b 30 83 e6 fe 89 f0 <8b> 7e 10 88 55 f0 e8 47 26 01 00 8a 55 f0 84 d2 74 17 f6 03 01 [ 95.341908] EIP: [] klist_put+0x12/0x62 SS:ESP 0068:f214fe1c [ 95.341908] CR2: 0000000000000010 [ 95.342357] ---[ end trace 8124d00ad871ad18 ]--- Signed-off-by: Ionut Nicu Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/ti_usb_3410_5052.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 90979a1f5311..c58ef5434733 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -365,9 +365,9 @@ failed_1port: static void __exit ti_exit(void) { + usb_deregister(&ti_usb_driver); usb_serial_deregister(&ti_1port_device); usb_serial_deregister(&ti_2port_device); - usb_deregister(&ti_usb_driver); } -- cgit v1.2.3 From f522aa8db193529e265a2c090f45757ce5b0e4f3 Mon Sep 17 00:00:00 2001 From: Nick Holloway Date: Wed, 26 Jan 2011 21:47:43 +0000 Subject: USB: Storage: Add unusual_devs entry for VTech Kidizoom commit c25f6b1591b158f7ae3b9132367d0fa6d632e70e upstream. This device suffers from the off-by-one error when reporting the capacity, so add entry with US_FL_FIX_CAPACITY. Signed-off-by: Nick Holloway Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index bc437a8460b5..b0c0a33910e8 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1396,6 +1396,13 @@ UNUSUAL_DEV( 0x0f19, 0x0105, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +/* Submitted by Nick Holloway */ +UNUSUAL_DEV( 0x0f88, 0x042e, 0x0100, 0x0100, + "VTech", + "Kidizoom", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Reported by Michael Stattmann */ UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000, "Sony Ericsson", -- cgit v1.2.3 From 5d2084b8acf15af976199fda0d199c2d71d479e0 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sat, 29 Jan 2011 15:32:52 +0100 Subject: USB: ftdi_sio: add ST Micro Connect Lite uart support commit 6ec2f46c4b4abf48c88c0ae7c476f347b97e1105 upstream. on ST Micro Connect Lite we have 4 port Part A and B for the JTAG Port C Uart Port D for PIO Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/ftdi_sio.c | 26 ++++++++++++++++++++++++++ drivers/usb/serial/ftdi_sio_ids.h | 6 ++++++ 2 files changed, 32 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index da67c3bb6100..cfd7637dd1f4 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -99,6 +99,7 @@ struct ftdi_sio_quirk { static int ftdi_jtag_probe(struct usb_serial *serial); static int ftdi_mtxorb_hack_setup(struct usb_serial *serial); static int ftdi_NDI_device_setup(struct usb_serial *serial); +static int ftdi_stmclite_probe(struct usb_serial *serial); static void ftdi_USB_UIRT_setup(struct ftdi_private *priv); static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv); @@ -122,6 +123,10 @@ static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { .port_probe = ftdi_HE_TIRA1_setup, }; +static struct ftdi_sio_quirk ftdi_stmclite_quirk = { + .probe = ftdi_stmclite_probe, +}; + /* * The 8U232AM has the same API as the sio except for: * - it can support MUCH higher baudrates; up to: @@ -809,6 +814,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) }, { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(ST_VID, ST_STMCLT1030_PID), + .driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; @@ -1689,6 +1696,25 @@ static int ftdi_jtag_probe(struct usb_serial *serial) return 0; } +/* + * First and second port on STMCLiteadaptors is reserved for JTAG interface + * and the forth port for pio + */ +static int ftdi_stmclite_probe(struct usb_serial *serial) +{ + struct usb_device *udev = serial->dev; + struct usb_interface *interface = serial->interface; + + dbg("%s", __func__); + + if (interface == udev->actconfig->interface[2]) + return 0; + + dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n"); + + return -ENODEV; +} + /* * The Matrix Orbital VK204-25-USB has an invalid IN endpoint. * We have to correct it if we want to read from it. diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index a2bb959059aa..329706b085c8 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1033,6 +1033,12 @@ #define STB_PID 0x0001 /* Sensor Terminal Board */ #define WHT_PID 0x0004 /* Wireless Handheld Terminal */ +/* + * STMicroelectonics + */ +#define ST_VID 0x0483 +#define ST_STMCLT1030_PID 0x3747 /* ST Micro Connect Lite STMCLT1030 */ + /* * Papouch products (http://www.papouch.com/) * Submitted by Folkert van Heusden -- cgit v1.2.3 From 8cb24112de67da453888fe7ddcf8b2e3b03401dd Mon Sep 17 00:00:00 2001 From: Arvid Ephraim Picciani Date: Tue, 25 Jan 2011 15:58:40 +0100 Subject: USB: cdc-acm: Adding second ACM channel support for Nokia N8 commit 721d92fc6373dee15846216f9d178ec240ec0fd7 upstream. This adds the N8 to the list of devices in cdc-acm, in order to get the secondary ACM device exposed. In the spirit of: http://kerneltrap.org/mailarchive/linux-usb/2010/9/4/6264554 Signed-off-by: Arvid Ephraim Picciani Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/class/cdc-acm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index a1aacb048eb3..01b74aa37ea8 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1613,6 +1613,7 @@ static const struct usb_device_id acm_ids[] = { { NOKIA_PCSUITE_ACM_INFO(0x0154), }, /* Nokia 5800 XpressMusic */ { NOKIA_PCSUITE_ACM_INFO(0x04ce), }, /* Nokia E90 */ { NOKIA_PCSUITE_ACM_INFO(0x01d4), }, /* Nokia E55 */ + { NOKIA_PCSUITE_ACM_INFO(0x0302), }, /* Nokia N8 */ { SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */ /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ -- cgit v1.2.3 From fd211cc38c1904b1e829e595a20f55e69eb4f368 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Thu, 27 Jan 2011 18:36:19 -0600 Subject: USB: ftdi_sio: Add VID=0x0647, PID=0x0100 for Acton Research spectrograph commit 28fe2eb0162a1d23370dd99ff7d0e35632b1ee91 upstream. Add the USB Vendor ID and Product ID for a Acton Research Corp. spectrograph device with a FTDI chip for serial I/O. Signed-off-by: Michael H Williamson Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index cfd7637dd1f4..b2c4c1c940e8 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -620,6 +620,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_OCEANIC_PID) }, { USB_DEVICE(TTI_VID, TTI_QL355P_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, + { USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) }, { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 329706b085c8..3523df534a27 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -517,6 +517,12 @@ #define RATOC_VENDOR_ID 0x0584 #define RATOC_PRODUCT_ID_USB60F 0xb020 +/* + * Acton Research Corp. + */ +#define ACTON_VID 0x0647 /* Vendor ID */ +#define ACTON_SPECTRAPRO_PID 0x0100 + /* * Contec products (http://www.contec.com) * Submitted by Daniel Sangorrin -- cgit v1.2.3 From 011fd193cd1ead28d3d408a6dae89ad0f4649a16 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 31 Jan 2011 10:56:37 -0500 Subject: USB: prevent buggy hubs from crashing the USB stack commit d199c96d41d80a567493e12b8e96ea056a1350c1 upstream. If anyone comes across a high-speed hub that (by mistake or by design) claims to have no Transaction Translators, plugging a full- or low-speed device into it will cause the USB stack to crash. This patch (as1446) prevents the problem by ignoring such devices, since the kernel has no way to communicate with them. Signed-off-by: Alan Stern Signed-off-by: Andi Kleen Tested-by: Perry Neben Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 53467b526b12..0b156a55c5a6 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2721,6 +2721,11 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, udev->ttport = hdev->ttport; } else if (udev->speed != USB_SPEED_HIGH && hdev->speed == USB_SPEED_HIGH) { + if (!hub->tt.hub) { + dev_err(&udev->dev, "parent hub has no TT\n"); + retval = -EINVAL; + goto fail; + } udev->tt = &hub->tt; udev->ttport = port1; } -- cgit v1.2.3 From a99686bd98eb3baccacdfa0e6becfa97c90f427b Mon Sep 17 00:00:00 2001 From: Ruben Smits Date: Sat, 11 Dec 2010 08:26:18 +0100 Subject: staging: comedi: add support for newer jr3 1-channel pci board commit 6292817d58637f85dd623cfe563c7f5ec4f4c470 upstream. add DEVICE_ID to table Signed-off-by: Ruben Smits Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/comedi/drivers/jr3_pci.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index d330b1886846..db31dfb080ba 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -53,6 +53,7 @@ Devices: [JR3] PCI force sensor board (jr3_pci) #define PCI_VENDOR_ID_JR3 0x1762 #define PCI_DEVICE_ID_JR3_1_CHANNEL 0x3111 +#define PCI_DEVICE_ID_JR3_1_CHANNEL_NEW 0x1111 #define PCI_DEVICE_ID_JR3_2_CHANNEL 0x3112 #define PCI_DEVICE_ID_JR3_3_CHANNEL 0x3113 #define PCI_DEVICE_ID_JR3_4_CHANNEL 0x3114 @@ -72,6 +73,8 @@ static DEFINE_PCI_DEVICE_TABLE(jr3_pci_pci_table) = { { PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { + PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL_NEW, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_2_CHANNEL, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_3_CHANNEL, @@ -808,6 +811,10 @@ static int jr3_pci_attach(struct comedi_device *dev, devpriv->n_channels = 1; } break; + case PCI_DEVICE_ID_JR3_1_CHANNEL_NEW:{ + devpriv->n_channels = 1; + } + break; case PCI_DEVICE_ID_JR3_2_CHANNEL:{ devpriv->n_channels = 2; } -- cgit v1.2.3 From b63383a733aaa1cfb15d7da2339e7d6a265d9ab0 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 19 Jan 2011 11:48:44 +0000 Subject: staging: comedi: ni_labpc: Use shared IRQ for PCMCIA card commit d1ce318496f5943d2cc5e20171fc383a59a1421f upstream. The ni_labpc driver module only requests a shared IRQ for PCI devices, requesting a non-shared IRQ for non-PCI devices. As this module is also used by the ni_labpc_cs module for certain National Instruments PCMCIA cards, it also needs to request a shared IRQ for PCMCIA devices, otherwise you get a IRQ mismatch with the CardBus controller. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/comedi/drivers/ni_labpc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 67c8a538802c..95bdc0d3e873 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -571,7 +571,8 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, /* grab our IRQ */ if (irq) { isr_flags = 0; - if (thisboard->bustype == pci_bustype) + if (thisboard->bustype == pci_bustype + || thisboard->bustype == pcmcia_bustype) isr_flags |= IRQF_SHARED; if (request_irq(irq, labpc_interrupt, isr_flags, driver_labpc.driver_name, dev)) { -- cgit v1.2.3 From ddad244f7a8d7ac810cefe919a750383d4dc7ff6 Mon Sep 17 00:00:00 2001 From: Ky Srinivasan Date: Thu, 16 Dec 2010 18:59:19 -0700 Subject: Staging: hv: fix sysfs symlink on hv block device commit 268eff909afaca93188d2d14554cbf824f6a0e41 upstream. The block device does not create the proper symlink in sysfs because we forgot to set up the gendisk structure properly. This patch fixes the issue. Signed-off-by: K. Y. Srinivasan Signed-off-by: Andi Kleen Cc: Hank Janssen Cc: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/blkvsc_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index 61bd0be5fb18..1886bc082c85 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -378,6 +378,7 @@ static int blkvsc_probe(struct device *device) blkdev->gd->first_minor = 0; blkdev->gd->fops = &block_ops; blkdev->gd->private_data = blkdev; + blkdev->gd->driverfs_dev = &(blkdev->device_ctx->device); sprintf(blkdev->gd->disk_name, "hd%c", 'a' + devnum); blkvsc_do_inquiry(blkdev); -- cgit v1.2.3 From 8bf615aa447b026c79847c0cbef5748add62c1ce Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Wed, 2 Feb 2011 13:42:58 -0800 Subject: staging: hv: Enable sending GARP packet after live migration commit 7c161d0b900ea9bd9fc5ea5d3fa9916e9eb0dd88 upstream. The hv_netvsc gets RNDIS_STATUS_MEDIA_CONNECT event after the VM is live migrated. Adding call to netif_notify_peers() for this event to send GARP (Gratuitous ARP) to notify network peers. Otherwise, the VM's network connection may stop after a live migration. This patch should also be applied to stable kernel 2.6.32 and later. Signed-off-by: Haiyang Zhang Signed-off-by: Hank Janssen Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/hv/netvsc_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 69cc8f763a0d..a2b8c6d1f2e8 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -249,6 +249,7 @@ static void netvsc_linkstatus_callback(struct hv_device *device_obj, if (status == 1) { netif_carrier_on(net); netif_wake_queue(net); + netif_notify_peers(net); } else { netif_carrier_off(net); netif_stop_queue(net); -- cgit v1.2.3 From 70f11ca245c351cc64db6f9b0fab31001b972413 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 23 Dec 2010 12:38:21 +0100 Subject: iwlagn: enable only rfkill interrupt when device is down commit 554d1d027b19265c4aa3f718b3126d2b86e09a08 upstream. Since commit 6cd0b1cb872b3bf9fc5de4536404206ab74bafdd "iwlagn: fix hw-rfkill while the interface is down", we enable interrupts when device is not ready to receive them. However hardware, when it is in some inconsistent state, can generate other than rfkill interrupts and crash the system. I can reproduce crash with "kernel BUG at drivers/net/wireless/iwlwifi/iwl-agn.c:1010!" message, when forcing firmware restarts. To fix only enable rfkill interrupt when down device and after probe. I checked patch on laptop with 5100 device, rfkill change is still passed to user space when device is down. Signed-off-by: Stanislaw Gruszka Acked-by: Wey-Yi Guy Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/iwlwifi/iwl-agn.c | 9 +++++---- drivers/net/wireless/iwlwifi/iwl-helpers.h | 6 ++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c7f56b4aeb89..6aa261402f88 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3112,9 +3112,10 @@ static void iwl_mac_stop(struct ieee80211_hw *hw) flush_workqueue(priv->workqueue); - /* enable interrupts again in order to receive rfkill changes */ + /* User space software may expect getting rfkill changes + * even if interface is down */ iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - iwl_enable_interrupts(priv); + iwl_enable_rfkill_int(priv); IWL_DEBUG_MAC80211(priv, "leave\n"); } @@ -3832,14 +3833,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * 8. Enable interrupts and read RFKILL state *********************************************/ - /* enable interrupts if needed: hw bug w/a */ + /* enable rfkill interrupt: hw bug w/a */ pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd); } - iwl_enable_interrupts(priv); + iwl_enable_rfkill_int(priv); /* If platform's RF_KILL switch is NOT set to KILL */ if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 3ff6b9d25a10..2f7ea66c1ed3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -163,6 +163,12 @@ static inline void iwl_disable_interrupts(struct iwl_priv *priv) IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); } +static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) +{ + IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); + iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); +} + static inline void iwl_enable_interrupts(struct iwl_priv *priv) { IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); -- cgit v1.2.3 From 724f5feecb5ec1b67db3b67b6aa45d08da2caf59 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Wed, 10 Nov 2010 05:03:15 -0800 Subject: ath9k: Fix bug in delimiter padding computation commit 39ec2997c374b528cdbf65099b6d6b8593a67f7f upstream. There is a roundng error in delimiter padding computation which causes severe throughput drop with some of AR9003. signed-off-by: Felix Fietkau Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/ath/ath9k/ath9k.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 5ea87736a6ae..dcfe6e1d1d1d 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -174,8 +174,8 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, /* returns delimiter padding required given the packet length */ #define ATH_AGGR_GET_NDELIM(_len) \ - (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \ - (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2) + (((_len) >= ATH_AGGR_MINPLEN) ? 0 : \ + DIV_ROUND_UP(ATH_AGGR_MINPLEN - (_len), ATH_AGGR_DELIM_SZ)) #define BAW_WITHIN(_start, _bawsz, _seqno) \ ((((_seqno) - (_start)) & 4095) < (_bawsz)) -- cgit v1.2.3 From 90b97746d7566dd0215f757dffcf6ae02017f533 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 17 Dec 2010 15:36:34 -0500 Subject: fix medium error problems with some arrays which can cause data corruption commit a8733c7baf457b071528e385a0b7d4aaec79287c upstream. Our current handling of medium error assumes that data is returned up to the bad sector. This assumption holds good for all disk devices, all DIF arrays and most ordinary arrays. However, an LSI array engine was recently discovered which reports a medium error without returning any data. This means that when we report good data up to the medium error, we've reported junk originally in the buffer as good. Worse, if the read consists of requested data plus a readahead, and the error occurs in readahead, we'll just strip off the readahead and report junk up to userspace as good data with no error. The fix for this is to have the error position computation take into account the amount of data returned by the driver using the scsi residual data. Unfortunately, not every driver fills in this data, but for those who don't, it's set to zero, which means we'll think a full set of data was transferred and the behaviour will be identical to the prior behaviour of the code (believe the buffer up to the error sector). All modern drivers seem to set the residual, so that should fix up the LSI failure/corruption case. Reported-by: Douglas Gilbert Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/scsi/sd.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index e4d9c515c292..2452686aa049 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1111,6 +1111,12 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) u64 end_lba = blk_rq_pos(scmd->request) + (scsi_bufflen(scmd) / 512); u64 bad_lba; int info_valid; + /* + * resid is optional but mostly filled in. When it's unused, + * its value is zero, so we assume the whole buffer transferred + */ + unsigned int transferred = scsi_bufflen(scmd) - scsi_get_resid(scmd); + unsigned int good_bytes; if (!blk_fs_request(scmd->request)) return 0; @@ -1144,7 +1150,8 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) /* This computation should always be done in terms of * the resolution of the device's medium. */ - return (bad_lba - start_lba) * scmd->device->sector_size; + good_bytes = (bad_lba - start_lba) * scmd->device->sector_size; + return min(good_bytes, transferred); } /** -- cgit v1.2.3 From b58639720eac254dcf92195d3ae08edd67863540 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 20 Jan 2011 17:26:44 -0600 Subject: libsas: fix runaway error handler problem commit 9ee91f7fb550a4c82f82d9818e42493484c754af upstream. libsas makes use of scsi_schedule_eh() but forgets to clear the host_eh_scheduled flag in its error handling routine. Because of this, the error handler thread never gets to sleep; it's constantly awake and trying to run the error routine leading to console spew and inability to run anything else (at least on a UP system). The fix is to clear the flag as we splice the work queue. Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/scsi/libsas/sas_scsi_host.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index a7890c6d878e..87f58f6a7ecc 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -649,6 +649,7 @@ void sas_scsi_recover_host(struct Scsi_Host *shost) spin_lock_irqsave(shost->host_lock, flags); list_splice_init(&shost->eh_cmd_q, &eh_work_q); + shost->host_eh_scheduled = 0; spin_unlock_irqrestore(shost->host_lock, flags); SAS_DPRINTK("Enter %s\n", __func__); -- cgit v1.2.3 From fbc633e83f67c91926ba25ee33ee9872c51e303f Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Tue, 4 Jan 2011 11:32:13 +0530 Subject: mpt2sas: Fix device removal handshake for zoned devices commit 4dc2757a2e9a9d1f2faee4fc6119276fc0061c16 upstream. When zoning end devices, the driver is not sending device removal handshake alogrithm to firmware. This results in controller firmware not sending sas topology add events the next time the device is added. The fix is the driver should be doing the device removal handshake even though the PHYSTATUS_VACANT bit is set in the PhyStatus of the event data. The current design is avoiding the handshake when the VACANT bit is set in the phy status. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index c5ff26a2a51d..04baaf499ece 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -2759,9 +2759,6 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc, u16 handle; for (i = 0 ; i < event_data->NumEntries; i++) { - if (event_data->PHY[i].PhyStatus & - MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) - continue; handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); if (!handle) continue; -- cgit v1.2.3 From e38e3219fdd87269cf63a696e5cc7b2e54d60405 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Tue, 4 Jan 2011 11:34:57 +0530 Subject: mpt2sas: Correct resizing calculation for max_queue_depth commit 11e1b961ab067ee3acaf723531da4d3f23e1d6f7 upstream. The ioc->hba_queue_depth is not properly resized when the controller firmware reports that it supports more outstanding IO than what can be fit inside the reply descriptor pool depth. This is reproduced by setting the controller global credits larger than 30,000. The bug results in an incorrect sizing of the queues. The fix is to resize the queue_size by dividing queue_diff by two. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/scsi/mpt2sas/mpt2sas_base.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 0ec1ed389c20..4878d602efd0 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -2050,9 +2050,9 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) /* adjust hba_queue_depth, reply_free_queue_depth, * and queue_size */ - ioc->hba_queue_depth -= queue_diff; - ioc->reply_free_queue_depth -= queue_diff; - queue_size -= queue_diff; + ioc->hba_queue_depth -= (queue_diff / 2); + ioc->reply_free_queue_depth -= (queue_diff / 2); + queue_size = facts->MaxReplyDescriptorPostQueueDepth; } ioc->reply_post_queue_depth = queue_size; -- cgit v1.2.3 From 2e001e82b7d37f374261b5f8290f58976363234b Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Tue, 4 Jan 2011 11:38:39 +0530 Subject: mpt2sas: Kernel Panic during Large Topology discovery commit 4224489f45b503f0a1f1cf310f76dc108f45689a upstream. There was a configuration page timing out during the initial port enable at driver load time. The port enable would fail, and this would result in the driver unloading itself, meanwhile the driver was accessing freed memory in another context resulting in the panic. The fix is to prevent access to freed memory once the driver had issued the diag reset which woke up the sleeping port enable process. The routine _base_reset_handler was reorganized so the last sleeping process woken up was the port_enable. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/scsi/mpt2sas/mpt2sas_base.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 4878d602efd0..09433dff2022 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -3736,6 +3736,8 @@ mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) static void _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) { + mpt2sas_scsih_reset_handler(ioc, reset_phase); + mpt2sas_ctl_reset_handler(ioc, reset_phase); switch (reset_phase) { case MPT2_IOC_PRE_RESET: dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " @@ -3766,8 +3768,6 @@ _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); break; } - mpt2sas_scsih_reset_handler(ioc, reset_phase); - mpt2sas_ctl_reset_handler(ioc, reset_phase); } /** @@ -3821,6 +3821,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, { int r; unsigned long flags; + u8 pe_complete = ioc->wait_for_port_enable_to_complete; dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, __func__)); @@ -3845,6 +3846,14 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, if (r) goto out; _base_reset_handler(ioc, MPT2_IOC_AFTER_RESET); + + /* If this hard reset is called while port enable is active, then + * there is no reason to call make_ioc_operational + */ + if (pe_complete) { + r = -EFAULT; + goto out; + } r = _base_make_ioc_operational(ioc, sleep_flag); if (!r) _base_reset_handler(ioc, MPT2_IOC_DONE_RESET); -- cgit v1.2.3 From 9c198dad83c19a05a11b5a195242f3e8dcbe55f4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 6 Jan 2011 08:16:04 -0200 Subject: radio-aimslab.c: Fix gcc 4.5+ bug commit e3c92215198cb6aa00ad38db2780faa6b72e0a3f upstream. gcc 4.5+ doesn't properly evaluate some inlined expressions. A previous patch were proposed by Andrew Morton using noinline. However, the entire inlined function is bogus, so let's just remove it and be happy. Reported-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/media/radio/radio-aimslab.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 5bf4985daede..19448144eb3a 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -31,7 +31,6 @@ #include /* Modules */ #include /* Initdata */ #include /* request_region */ -#include /* udelay */ #include /* kernel radio structs */ #include /* for KERNEL_VERSION MACRO */ #include /* outb, outb_p */ @@ -71,27 +70,17 @@ static struct rtrack rtrack_card; /* local things */ -static void sleep_delay(long n) -{ - /* Sleep nicely for 'n' uS */ - int d = n / msecs_to_jiffies(1000); - if (!d) - udelay(n); - else - msleep(jiffies_to_msecs(d)); -} - static void rt_decvol(struct rtrack *rt) { outb(0x58, rt->io); /* volume down + sigstr + on */ - sleep_delay(100000); + msleep(100); outb(0xd8, rt->io); /* volume steady + sigstr + on */ } static void rt_incvol(struct rtrack *rt) { outb(0x98, rt->io); /* volume up + sigstr + on */ - sleep_delay(100000); + msleep(100); outb(0xd8, rt->io); /* volume steady + sigstr + on */ } @@ -120,7 +109,7 @@ static int rt_setvol(struct rtrack *rt, int vol) if (vol == 0) { /* volume = 0 means mute the card */ outb(0x48, rt->io); /* volume down but still "on" */ - sleep_delay(2000000); /* make sure it's totally down */ + msleep(2000); /* make sure it's totally down */ outb(0xd0, rt->io); /* volume steady, off */ rt->curvol = 0; /* track the volume state! */ mutex_unlock(&rt->lock); @@ -155,7 +144,7 @@ static void send_0_byte(struct rtrack *rt) outb_p(128+64+16+8+ 1, rt->io); /* on + wr-enable + data low */ outb_p(128+64+16+8+2+1, rt->io); /* clock */ } - sleep_delay(1000); + msleep(1); } static void send_1_byte(struct rtrack *rt) @@ -169,7 +158,7 @@ static void send_1_byte(struct rtrack *rt) outb_p(128+64+16+8+4+2+1, rt->io); /* clock */ } - sleep_delay(1000); + msleep(1); } static int rt_setfreq(struct rtrack *rt, unsigned long freq) @@ -427,7 +416,7 @@ static int __init rtrack_init(void) /* this ensures that the volume is all the way down */ outb(0x48, rt->io); /* volume down but still "on" */ - sleep_delay(2000000); /* make sure it's totally down */ + msleep(2000); /* make sure it's totally down */ outb(0xc0, rt->io); /* steady volume, mute card */ return 0; -- cgit v1.2.3 From 9e5ad61f8d81da0b58535ac2cf60d36e26ca567a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Oct 2010 17:51:15 -0300 Subject: em28xx: Fix audio input for Terratec Grabby commit a3fa904ec79b94f0db7faed010ff94d42f7d1d47 upstream. The audio input line was wrong. Fix it. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/media/video/em28xx/em28xx-cards.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 3a4fd8514511..2fa5bb4a18b4 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1605,11 +1605,11 @@ struct em28xx_board em28xx_boards[] = { .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO2, + .amux = EM28XX_AMUX_LINE_IN, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_VIDEO2, + .amux = EM28XX_AMUX_LINE_IN, } }, }, [EM2860_BOARD_TERRATEC_AV350] = { -- cgit v1.2.3 From c04265109cbe48d623bda599e96a3e9fa7b51db7 Mon Sep 17 00:00:00 2001 From: Raymond Yau Date: Sun, 16 Jan 2011 10:55:54 +0800 Subject: ALSA : au88x0 - Limit number of channels to fix Oops via OSS emu commit d9ab344336f74c012f6643ed3d1ad8ca0136de3b upstream. Fix playback/capture channels patch to change supported playback channels of au8830 to 1,2,4 and capture channels to 1,2. This prevent oops when oss emulation use SNDCTL_DSP_CHANNELS to set 3 Channels Signed-off-by: Raymond Yau Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/au88x0/au88x0_pcm.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c index b9d2f202cf9b..5439d662d104 100644 --- a/sound/pci/au88x0/au88x0_pcm.c +++ b/sound/pci/au88x0/au88x0_pcm.c @@ -42,11 +42,7 @@ static struct snd_pcm_hardware snd_vortex_playback_hw_adb = { .rate_min = 5000, .rate_max = 48000, .channels_min = 1, -#ifdef CHIP_AU8830 - .channels_max = 4, -#else .channels_max = 2, -#endif .buffer_bytes_max = 0x10000, .period_bytes_min = 0x1, .period_bytes_max = 0x1000, @@ -115,6 +111,17 @@ static struct snd_pcm_hardware snd_vortex_playback_hw_wt = { .periods_max = 64, }; #endif +#ifdef CHIP_AU8830 +static unsigned int au8830_channels[3] = { + 1, 2, 4, +}; + +static struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = { + .count = ARRAY_SIZE(au8830_channels), + .list = au8830_channels, + .mask = 0, +}; +#endif /* open callback */ static int snd_vortex_pcm_open(struct snd_pcm_substream *substream) { @@ -156,6 +163,15 @@ static int snd_vortex_pcm_open(struct snd_pcm_substream *substream) if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB || VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_I2S) runtime->hw = snd_vortex_playback_hw_adb; +#ifdef CHIP_AU8830 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && + VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) { + runtime->hw.channels_max = 4; + snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &hw_constraints_au8830_channels); + } +#endif substream->runtime->private_data = NULL; } #ifndef CHIP_AU8810 -- cgit v1.2.3 From cf789a9168dc89e10926d85e14257843945d99a6 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 25 Jan 2011 19:44:26 +0100 Subject: ALSA: HDA: Fix dmesg output of HDMI supported bits commit d757534ed15387202e322854cd72dc58bbb975de upstream. This typo caused the dmesg output of the supported bits of HDMI to be cut off early. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/hda_eld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index d8da18a9e98b..f5852006d8ba 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -381,7 +381,7 @@ static void hdmi_show_short_audio_desc(struct cea_sad *a) snd_print_pcm_rates(a->rates, buf, sizeof(buf)); if (a->format == AUDIO_CODING_TYPE_LPCM) - snd_print_pcm_bits(a->sample_bits, buf2 + 8, sizeof(buf2 - 8)); + snd_print_pcm_bits(a->sample_bits, buf2 + 8, sizeof(buf2) - 8); else if (a->max_bitrate) snprintf(buf2, sizeof(buf2), ", max bitrate = %d", a->max_bitrate); -- cgit v1.2.3 From 76ad0710fcbdbea25be092f68cc55a40703706af Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 2 Feb 2011 17:16:38 +0100 Subject: ALSA: hda - Fix memory leaks in conexant jack arrays commit 70f7db11c45a313b23922cacf248c613c3b2144c upstream. The Conexant codec driver adds the jack arrays in init callback which may be called also in each PM resume. This results in the addition of new jack element at each time. The fix is to check whether the requested jack is already present in the array. Reference: Novell bug 668929 https://bugzilla.novell.com/show_bug.cgi?id=668929 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_conexant.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index aeea1cd0bcaa..ffba0a1b2498 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -391,10 +391,16 @@ static int conexant_add_jack(struct hda_codec *codec, struct conexant_spec *spec; struct conexant_jack *jack; const char *name; - int err; + int i, err; spec = codec->spec; snd_array_init(&spec->jacks, sizeof(*jack), 32); + + jack = spec->jacks.list; + for (i = 0; i < spec->jacks.used; i++, jack++) + if (jack->nid == nid) + return 0 ; /* already present */ + jack = snd_array_new(&spec->jacks); name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ; -- cgit v1.2.3 From 72784680f1c730c89a067930f8d4ec0e88d488ed Mon Sep 17 00:00:00 2001 From: "Edgar (gimli) Hucek" Date: Tue, 9 Nov 2010 17:38:42 +0100 Subject: input: bcm5974: Add support for MacBookAir3 commit 6021afcf19d8c6f5db6d11cadcfb6a22d0c28a48 upstream. This patch adds support for the MacBookAir3,1 and MacBookAir3,2 models. [rydberg@euromail.se: touchpad range calibration] Signed-off-by: Edgar (gimli) Hucek Signed-off-by: Henrik Rydberg Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/input/mouse/bcm5974.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 6dedded27222..3564cdab4109 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -55,6 +55,14 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 +/* MacbookAir3,2 (unibody), aka wellspring5 */ +#define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI 0x023f +#define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO 0x0240 +#define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS 0x0241 +/* MacbookAir3,1 (unibody), aka wellspring4 */ +#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 +#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 +#define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 #define BCM5974_DEVICE(prod) { \ .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ @@ -80,6 +88,14 @@ static const struct usb_device_id bcm5974_table[] = { BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), + /* MacbookAir3,2 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_ISO), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_JIS), + /* MacbookAir3,1 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), /* Terminating entry */ {} }; @@ -234,6 +250,30 @@ static const struct bcm5974_config bcm5974_config_table[] = { { DIM_X, DIM_X / SN_COORD, -4460, 5166 }, { DIM_Y, DIM_Y / SN_COORD, -75, 6700 } }, + { + USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI, + USB_DEVICE_ID_APPLE_WELLSPRING4_ISO, + USB_DEVICE_ID_APPLE_WELLSPRING4_JIS, + HAS_INTEGRATED_BUTTON, + 0x84, sizeof(struct bt_data), + 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4620, 5140 }, + { DIM_Y, DIM_Y / SN_COORD, -150, 6600 } + }, + { + USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI, + USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO, + USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS, + HAS_INTEGRATED_BUTTON, + 0x84, sizeof(struct bt_data), + 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4616, 5112 }, + { DIM_Y, DIM_Y / SN_COORD, -142, 5234 } + }, {} }; -- cgit v1.2.3 From a0f33df166682a70c1d8aaa28aadbb4e4d4e9370 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Feb 2011 16:15:44 +0100 Subject: ALSA: hrtimer: handle delayed timer interrupts commit b1d4f7f4bdcf9915c41ff8cfc4425c84dabb1fde upstream. If a timer interrupt was delayed too much, hrtimer_forward_now() will forward the timer expiry more than once. When this happens, the additional number of elapsed ALSA timer ticks must be passed to snd_timer_interrupt() to prevent the ALSA timer from falling behind. This mostly fixes MIDI slowdown problems on highly-loaded systems with badly behaved interrupt handlers. Signed-off-by: Clemens Ladisch Signed-off-by: Andi Kleen Reported-and-tested-by: Arthur Marsh Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/core/hrtimer.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c index 7730575bfadd..07efa29dfd4a 100644 --- a/sound/core/hrtimer.c +++ b/sound/core/hrtimer.c @@ -45,12 +45,13 @@ static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt) { struct snd_hrtimer *stime = container_of(hrt, struct snd_hrtimer, hrt); struct snd_timer *t = stime->timer; + unsigned long oruns; if (!atomic_read(&stime->running)) return HRTIMER_NORESTART; - hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution)); - snd_timer_interrupt(stime->timer, t->sticks); + oruns = hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution)); + snd_timer_interrupt(stime->timer, t->sticks * oruns); if (!atomic_read(&stime->running)) return HRTIMER_NORESTART; -- cgit v1.2.3 From 86cd20034021d74ebd0e79e96ef4d74d7e802486 Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Fri, 14 Jan 2011 15:59:13 +0000 Subject: ASoC: WM8990: msleep() takes milliseconds not jiffies commit 7ebcf5d6021a696680ee77d9162a2edec2d671dd upstream. Signed-off-by: Dimitris Papastamos Acked-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/soc/codecs/wm8990.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index c018772cc430..bdbfac7225c0 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -1185,7 +1185,7 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, WM8990_VMIDTOG); /* Delay to allow output caps to discharge */ - msleep(msecs_to_jiffies(300)); + msleep(300); /* Disable VMIDTOG */ snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | @@ -1197,17 +1197,17 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, /* Enable outputs */ snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00); - msleep(msecs_to_jiffies(50)); + msleep(50); /* Enable VMID at 2x50k */ snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02); - msleep(msecs_to_jiffies(100)); + msleep(100); /* Enable VREF */ snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03); - msleep(msecs_to_jiffies(600)); + msleep(600); /* Enable BUFIOEN */ snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | @@ -1252,7 +1252,7 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, /* Disable VMID */ snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01); - msleep(msecs_to_jiffies(300)); + msleep(300); /* Enable all output discharge bits */ snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE | -- cgit v1.2.3 From 2045cadb2357c23a0bb334b993af0f2e55a1d8fb Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 11 Jan 2011 19:57:33 -0500 Subject: ASoC: Blackfin AC97: fix build error after multi-component update commit e9c2048915048d605fd76539ddd96f00d593e1eb upstream. We need to tweak how we query the active capture/playback state after the recent overhauls of common code. Signed-off-by: Mike Frysinger Acked-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/soc/blackfin/bf5xx-ac97.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index 523b7fc33f4e..b69cd4b4d3f0 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c @@ -261,9 +261,9 @@ static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) pr_debug("%s : sport %d\n", __func__, dai->id); if (!dai->active) return 0; - if (dai->capture.active) + if (dai->capture_active) sport_rx_stop(sport); - if (dai->playback.active) + if (dai->playback_active) sport_tx_stop(sport); return 0; } -- cgit v1.2.3 From 5df006274e1b1701e2fa185808fcee59ebb7c108 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 21 Jan 2011 15:54:57 +0000 Subject: NFS: Fix "kernel BUG at fs/aio.c:554!" commit 839f7ad6932d95f4d5ae7267b95c574714ff3d5b upstream. Nick Piggin reports: > I'm getting use after frees in aio code in NFS > > [ 2703.396766] Call Trace: > [ 2703.396858] [] ? native_sched_clock+0x27/0x80 > [ 2703.396959] [] ? put_lock_stats+0xe/0x40 > [ 2703.397058] [] ? lock_release_holdtime+0xa8/0x140 > [ 2703.397159] [] lock_acquire+0x95/0x1b0 > [ 2703.397260] [] ? aio_put_req+0x2b/0x60 > [ 2703.397361] [] ? get_parent_ip+0x11/0x50 > [ 2703.397464] [] _raw_spin_lock_irq+0x41/0x80 > [ 2703.397564] [] ? aio_put_req+0x2b/0x60 > [ 2703.397662] [] aio_put_req+0x2b/0x60 > [ 2703.397761] [] do_io_submit+0x2be/0x7c0 > [ 2703.397895] [] sys_io_submit+0xb/0x10 > [ 2703.397995] [] system_call_fastpath+0x16/0x1b > > Adding some tracing, it is due to nfs completing the request then > returning something other than -EIOCBQUEUED, so aio.c > also completes the request. To address this, prevent the NFS direct I/O engine from completing async iocbs when the forward path returns an error without starting any I/O. This fix appears to survive ^C during both "xfstest no. 208" and "fsx -Z." It's likely this bug has existed for a very long while, as we are seeing very similar symptoms in OEL 5. Copying stable. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfs/direct.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index ad4cd31d6050..b1c23b7c97cc 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -402,15 +402,18 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, pos += vec->iov_len; } + /* + * If no bytes were started, return the error, and let the + * generic layer handle the completion. + */ + if (requested_bytes == 0) { + nfs_direct_req_release(dreq); + return result < 0 ? result : -EIO; + } + if (put_dreq(dreq)) nfs_direct_complete(dreq); - - if (requested_bytes != 0) - return 0; - - if (result < 0) - return result; - return -EIO; + return 0; } static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, @@ -830,15 +833,18 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, pos += vec->iov_len; } + /* + * If no bytes were started, return the error, and let the + * generic layer handle the completion. + */ + if (requested_bytes == 0) { + nfs_direct_req_release(dreq); + return result < 0 ? result : -EIO; + } + if (put_dreq(dreq)) nfs_direct_write_complete(dreq, dreq->inode); - - if (requested_bytes != 0) - return 0; - - if (result < 0) - return result; - return -EIO; + return 0; } static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, -- cgit v1.2.3 From 1d2b536410df084435e2453a504ad2fedd46b690 Mon Sep 17 00:00:00 2001 From: Paul Fox Date: Wed, 12 Jan 2011 17:00:07 -0800 Subject: rtc-cmos: fix suspend/resume commit 2fb08e6ca9f00d1aedb3964983e9c8f84b36b807 upstream. rtc-cmos was setting suspend/resume hooks at the device_driver level. However, the platform bus code (drivers/base/platform.c) only looks for resume hooks at the dev_pm_ops level, or within the platform_driver. Switch rtc_cmos to use dev_pm_ops so that suspend/resume code is executed again. Paul said: : The user visible symptom in our (XO laptop) case was that rtcwake would : fail to wake the laptop. The RTC alarm would expire, but the wakeup : wasn't unmasked. : : As for severity, the impact may have been reduced because if I recall : correctly, the bug only affected platforms with CONFIG_PNP disabled. Signed-off-by: Paul Fox Signed-off-by: Daniel Drake Acked-by: Rafael J. Wysocki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/rtc/rtc-cmos.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 11b8ea29d2b7..bf588d97b59a 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -36,6 +36,7 @@ #include #include #include +#include /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ #include @@ -850,7 +851,7 @@ static void __exit cmos_do_remove(struct device *dev) #ifdef CONFIG_PM -static int cmos_suspend(struct device *dev, pm_message_t mesg) +static int cmos_suspend(struct device *dev) { struct cmos_rtc *cmos = dev_get_drvdata(dev); unsigned char tmp; @@ -898,7 +899,7 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg) */ static inline int cmos_poweroff(struct device *dev) { - return cmos_suspend(dev, PMSG_HIBERNATE); + return cmos_suspend(dev); } static int cmos_resume(struct device *dev) @@ -945,9 +946,9 @@ static int cmos_resume(struct device *dev) return 0; } +static SIMPLE_DEV_PM_OPS(cmos_pm_ops, cmos_suspend, cmos_resume); + #else -#define cmos_suspend NULL -#define cmos_resume NULL static inline int cmos_poweroff(struct device *dev) { @@ -1083,7 +1084,7 @@ static void __exit cmos_pnp_remove(struct pnp_dev *pnp) static int cmos_pnp_suspend(struct pnp_dev *pnp, pm_message_t mesg) { - return cmos_suspend(&pnp->dev, mesg); + return cmos_suspend(&pnp->dev); } static int cmos_pnp_resume(struct pnp_dev *pnp) @@ -1163,8 +1164,9 @@ static struct platform_driver cmos_platform_driver = { .shutdown = cmos_platform_shutdown, .driver = { .name = (char *) driver_name, - .suspend = cmos_suspend, - .resume = cmos_resume, +#ifdef CONFIG_PM + .pm = &cmos_pm_ops, +#endif } }; -- cgit v1.2.3 From 377490f5fdb3f967667ea0d2634938a671625f06 Mon Sep 17 00:00:00 2001 From: Don Fry Date: Sun, 6 Feb 2011 09:29:45 -0800 Subject: iwlagn: Re-enable RF_KILL interrupt when down commit 3dd823e6b86407aed1a025041d8f1df77e43a9c8 upstream. With commit 554d1d027b19265c4aa3f718b3126d2b86e09a08 only one RF_KILL interrupt will be seen by the driver when the interface is down. Re-enable the interrupt when it occurs to see all transitions. Signed-off-by: Don Fry Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6aa261402f88..8a2c4d73e4ef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1205,6 +1205,9 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) /* only Re-enable if diabled by irq */ if (test_bit(STATUS_INT_ENABLED, &priv->status)) iwl_enable_interrupts(priv); + /* Re-enable RF_KILL if it occurred */ + else if (handled & CSR_INT_BIT_RF_KILL) + iwl_enable_rfkill_int(priv); #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { @@ -1420,6 +1423,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) /* only Re-enable if diabled by irq */ if (test_bit(STATUS_INT_ENABLED, &priv->status)) iwl_enable_interrupts(priv); + /* Re-enable RF_KILL if it occurred */ + else if (handled & CSR_INT_BIT_RF_KILL) + iwl_enable_rfkill_int(priv); } /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ -- cgit v1.2.3 From 6cc795e4261bad5beb01adb0125e886c8750ac5c Mon Sep 17 00:00:00 2001 From: Thomas Taranowski Date: Wed, 12 Jan 2011 17:00:44 -0800 Subject: rapidio: fix hang on RapidIO doorbell queue full condition commit 12a4dc43911785f51a596f771ae0701b18d436f1 upstream. In fsl_rio_dbell_handler() the code currently simply acknowledges the QFI queue full interrupt, but does nothing to resolve the queue full condition. Instead, it jumps to the end of the isr. When a queue full condition occurs, the isr is then re-entered immediately and continually, forever. The fix is to just fall through and read out current doorbell entries. Signed-off-by: Thomas Taranowski Signed-off-by: Andi Kleen Cc: Alexandre Bounine Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang Cc: Thomas Moll Cc: Micha Nelissen Cc: Benjamin Herrenschmidt Cc: Grant Likely Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/sysdev/fsl_rio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 30e1626b2e85..494a63c1cbd0 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -952,7 +952,6 @@ fsl_rio_dbell_handler(int irq, void *dev_instance) if (dsr & DOORBELL_DSR_QFI) { pr_info("RIO: doorbell queue full\n"); out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_QFI); - goto out; } /* XXX Need to check/dispatch until queue empty */ -- cgit v1.2.3 From ca41567c53cdcc735571092e838d996c1150c70b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 22 Dec 2010 10:06:36 +0100 Subject: PCI: pci-stub: ignore zero-length id parameters commit 99a0fadf561e1f553c08f0a29f8b2578f55dd5f0 upstream. pci-stub uses strsep() to separate list of ids and generates a warning message when it fails to parse an id. However, not specifying the parameter results in ids set to an empty string. strsep() happily returns the empty string as the first token and thus triggers the warning message spuriously. Make the tokner ignore zero length ids. Reported-by: Chris Wright Reported-by: Prasad Joshi Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/pci/pci-stub.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/pci/pci-stub.c b/drivers/pci/pci-stub.c index f7b68ca6cc98..4ae494bb1d50 100644 --- a/drivers/pci/pci-stub.c +++ b/drivers/pci/pci-stub.c @@ -54,6 +54,9 @@ static int __init pci_stub_init(void) subdevice = PCI_ANY_ID, class=0, class_mask=0; int fields; + if (!strlen(id)) + continue; + fields = sscanf(id, "%x:%x:%x:%x:%x:%x", &vendor, &device, &subvendor, &subdevice, &class, &class_mask); -- cgit v1.2.3 From bd5235a5e5c6b1f180722a46611ab110d06adb69 Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Fri, 7 Jan 2011 02:55:06 -0600 Subject: virtio: remove virtio-pci root device commit 8b3bb3ecf1934ac4a7005ad9017de1127e2fbd2f upstream. We sometimes need to map between the virtio device and the given pci device. One such use is OS installer that gets the boot pci device from BIOS and needs to find the relevant block device. Since it can't, installation fails. Instead of creating a top-level devices/virtio-pci directory, create each device under the corresponding pci device node. Symlinks to all virtio-pci devices can be found under the pci driver link in bus/pci/drivers/virtio-pci/devices, and all virtio devices under drivers/bus/virtio/devices. Signed-off-by: Milton Miller Signed-off-by: Rusty Russell Acked-by: Michael S. Tsirkin Signed-off-by: Andi Kleen Tested-by: Michael S. Tsirkin Acked-by: Gleb Natapov Tested-by: "Daniel P. Berrange" Signed-off-by: Greg Kroah-Hartman --- drivers/virtio/virtio_pci.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index ef8d9d558fc7..4fb5b2bf2348 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -96,11 +96,6 @@ static struct pci_device_id virtio_pci_id_table[] = { MODULE_DEVICE_TABLE(pci, virtio_pci_id_table); -/* A PCI device has it's own struct device and so does a virtio device so - * we create a place for the virtio devices to show up in sysfs. I think it - * would make more sense for virtio to not insist on having it's own device. */ -static struct device *virtio_pci_root; - /* Convert a generic virtio device to our structure */ static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev) { @@ -629,7 +624,7 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev, if (vp_dev == NULL) return -ENOMEM; - vp_dev->vdev.dev.parent = virtio_pci_root; + vp_dev->vdev.dev.parent = &pci_dev->dev; vp_dev->vdev.dev.release = virtio_pci_release_dev; vp_dev->vdev.config = &virtio_pci_config_ops; vp_dev->pci_dev = pci_dev; @@ -717,17 +712,7 @@ static struct pci_driver virtio_pci_driver = { static int __init virtio_pci_init(void) { - int err; - - virtio_pci_root = root_device_register("virtio-pci"); - if (IS_ERR(virtio_pci_root)) - return PTR_ERR(virtio_pci_root); - - err = pci_register_driver(&virtio_pci_driver); - if (err) - root_device_unregister(virtio_pci_root); - - return err; + return pci_register_driver(&virtio_pci_driver); } module_init(virtio_pci_init); @@ -735,7 +720,6 @@ module_init(virtio_pci_init); static void __exit virtio_pci_exit(void) { pci_unregister_driver(&virtio_pci_driver); - root_device_unregister(virtio_pci_root); } module_exit(virtio_pci_exit); -- cgit v1.2.3 From 2be4ae77eca91af0f0577f1a174f3eae0797df2b Mon Sep 17 00:00:00 2001 From: Sven Neumann Date: Fri, 12 Nov 2010 11:36:22 +0100 Subject: ds2760_battery: Fix calculation of time_to_empty_now commit 86af95039b69a90db15294eb1f9c147f1df0a8ea upstream. A check against division by zero was modified in commit b0525b48. Since this change time_to_empty_now is always reported as zero while the battery is discharging and as a negative value while the battery is charging. This is because current is negative while the battery is discharging. Fix the check introduced by commit b0525b48 so that time_to_empty_now is reported correctly during discharge and as zero while charging. Signed-off-by: Sven Neumann Acked-by: Daniel Mack Signed-off-by: Anton Vorontsov Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/power/ds2760_battery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c index 4d3b27228a2e..c8d26df9f145 100644 --- a/drivers/power/ds2760_battery.c +++ b/drivers/power/ds2760_battery.c @@ -212,7 +212,7 @@ static int ds2760_battery_read_status(struct ds2760_device_info *di) if (di->rem_capacity > 100) di->rem_capacity = 100; - if (di->current_uA >= 100L) + if (di->current_uA < -100L) di->life_sec = -((di->accum_current_uAh - di->empty_uAh) * 36L) / (di->current_uA / 100L); else -- cgit v1.2.3 From c8ff6363cfcfe2192cc45c14bfda8b99431aa65f Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 6 Jan 2011 23:47:52 +0100 Subject: p54: fix sequence no. accounting off-by-one error commit 3b5c5827d1f80ad8ae844a8b1183f59ddb90fe25 upstream. P54_HDR_FLAG_DATA_OUT_SEQNR is meant to tell the firmware that "the frame's sequence number has already been set by the application." Whereas IEEE80211_TX_CTL_ASSIGN_SEQ is set for frames which lack a valid sequence number and either the driver or firmware has to assign one. Yup, it's the exact opposite! Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/p54/txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index ccb2dd1bf023..9ad0f5f0c884 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -616,7 +616,7 @@ static void p54_tx_80211_header(struct p54_common *priv, struct sk_buff *skb, else *burst_possible = false; - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) + if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) *flags |= P54_HDR_FLAG_DATA_OUT_SEQNR; if (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE) -- cgit v1.2.3 From d941e905c951364db60f5ad802c8730fc2526d1a Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 14 Jan 2011 22:03:49 +0100 Subject: i2c: Unregister dummy devices last on adapter removal commit 5219bf884b6e2b54e734ca1799b6f0014bb2b4b7 upstream. Remove real devices first and dummy devices last. This gives device driver which instantiated dummy devices themselves a chance to clean them up before we do. Signed-off-by: Jean Delvare Signed-off-by: Andi Kleen Tested-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/i2c-core.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 0815e10da7c6..9e6aa8d4845e 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -921,6 +921,14 @@ static int i2c_do_del_adapter(struct i2c_driver *driver, } static int __unregister_client(struct device *dev, void *dummy) +{ + struct i2c_client *client = i2c_verify_client(dev); + if (client && strcmp(client->name, "dummy")) + i2c_unregister_device(client); + return 0; +} + +static int __unregister_dummy(struct device *dev, void *dummy) { struct i2c_client *client = i2c_verify_client(dev); if (client) @@ -977,8 +985,12 @@ int i2c_del_adapter(struct i2c_adapter *adap) i2c_unlock_adapter(adap); /* Detach any active clients. This can't fail, thus we do not - checking the returned value. */ + * check the returned value. This is a two-pass process, because + * we can't remove the dummy devices during the first pass: they + * could have been instantiated by real devices wishing to clean + * them up properly, so we give them a chance to do that first. */ res = device_for_each_child(&adap->dev, NULL, __unregister_client); + res = device_for_each_child(&adap->dev, NULL, __unregister_dummy); #ifdef CONFIG_I2C_COMPAT class_compat_remove_link(i2c_adapter_compat_class, &adap->dev, -- cgit v1.2.3 From 69057aa6b8d7dc5e73efe4e157e5657ec7850c02 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 9 Jan 2011 08:38:48 +0100 Subject: serial: unbreak billionton CF card commit d0694e2aeb815042aa0f3e5036728b3db4446f1d upstream. Unbreak Billionton CF bluetooth card. This actually fixes a regression on zaurus. Signed-off-by: Pavel Machek Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/serial/8250.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 891e1dd65f24..5bab62d214b3 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -256,7 +256,8 @@ static const struct serial8250_config uart_config[] = { .fifo_size = 128, .tx_loadsz = 128, .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, + /* UART_CAP_EFR breaks billionon CF bluetooth card. */ + .flags = UART_CAP_FIFO | UART_CAP_SLEEP, }, [PORT_RSA] = { .name = "RSA", -- cgit v1.2.3 From 663fa622fa8a14a5f06fad75adb0fcec41c1d82f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 10 Feb 2011 15:01:22 -0800 Subject: ptrace: use safer wake up on ptrace_detach() commit 01e05e9a90b8f4c3997ae0537e87720eb475e532 upstream. The wake_up_process() call in ptrace_detach() is spurious and not interlocked with the tracee state. IOW, the tracee could be running or sleeping in any place in the kernel by the time wake_up_process() is called. This can lead to the tracee waking up unexpectedly which can be dangerous. The wake_up is spurious and should be removed but for now reduce its toxicity by only waking up if the tracee is in TRACED or STOPPED state. This bug can possibly be used as an attack vector. I don't think it will take too much effort to come up with an attack which triggers oops somewhere. Most sleeps are wrapped in condition test loops and should be safe but we have quite a number of places where sleep and wakeup conditions are expected to be interlocked. Although the window of opportunity is tiny, ptrace can be used by non-privileged users and with some loading the window can definitely be extended and exploited. Signed-off-by: Tejun Heo Acked-by: Roland McGrath Acked-by: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/ptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 74a3d693c196..752321eeca8b 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -313,7 +313,7 @@ int ptrace_detach(struct task_struct *child, unsigned int data) child->exit_code = data; dead = __ptrace_detach(current, child); if (!child->exit_state) - wake_up_process(child); + wake_up_state(child, TASK_TRACED | TASK_STOPPED); } write_unlock_irq(&tasklist_lock); -- cgit v1.2.3 From 9c452576359d2ffae23d13274c053fbbeceb90a6 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Wed, 2 Feb 2011 17:02:55 -0800 Subject: x86, mtrr: Avoid MTRR reprogramming on BP during boot on UP platforms commit f7448548a9f32db38f243ccd4271617758ddfe2c upstream. Markus Kohn ran into a hard hang regression on an acer aspire 1310, when acpi is enabled. git bisect showed the following commit as the bad one that introduced the boot regression. commit d0af9eed5aa91b6b7b5049cae69e5ea956fd85c3 Author: Suresh Siddha Date: Wed Aug 19 18:05:36 2009 -0700 x86, pat/mtrr: Rendezvous all the cpus for MTRR/PAT init Because of the UP configuration of that platform, native_smp_prepare_cpus() bailed out (in smp_sanity_check()) before doing the set_mtrr_aps_delayed_init() Further down the boot path, native_smp_cpus_done() will call the delayed MTRR initialization for the AP's (mtrr_aps_init()) with mtrr_aps_delayed_init not set. This resulted in the boot processor reprogramming its MTRR's to the values seen during the start of the OS boot. While this is not needed ideally, this shouldn't have caused any side-effects. This is because the reprogramming of MTRR's (set_mtrr_state() that gets called via set_mtrr()) will check if the live register contents are Signed-off-by: Andi Kleen different from what is being asked to write and will do the actual write only if they are different. BP's mtrr state is read during the start of the OS boot and typically nothing would have changed when we ask to reprogram it on BP again because of the above scenario on an UP platform. So on a normal UP platform no reprogramming of BP MTRR MSR's happens and all is well. However, on this platform, bios seems to be modifying the fixed mtrr range registers between the start of OS boot and when we double check the live registers for reprogramming BP MTRR registers. And as the live registers are modified, we end up reprogramming the MTRR's to the state seen during the start of the OS boot. During ACPI initialization, something in the bios (probably smi handler?) don't like this fact and results in a hard lockup. We didn't see this boot hang issue on this platform before the commit d0af9eed5aa91b6b7b5049cae69e5ea956fd85c3, because only the AP's (if any) will program its MTRR's to the value that BP had at the start of the OS boot. Fix this issue by checking mtrr_aps_delayed_init before continuing further in the mtrr_aps_init(). Now, only AP's (if any) will program its MTRR's to the BP values during boot. Addresses https://bugzilla.novell.com/show_bug.cgi?id=623393 [ By the way, this behavior of the bios modifying MTRR's after the start of the OS boot is not common and the kernel is not prepared to handle this situation well. Irrespective of this issue, during suspend/resume, linux kernel will try to reprogram the BP's MTRR values to the values seen during the start of the OS boot. So suspend/resume might be already broken on this platform for all linux kernel versions. ] Reported-and-bisected-by: Markus Kohn Tested-by: Markus Kohn Signed-off-by: Suresh Siddha Cc: Thomas Renninger Cc: Rafael Wysocki Cc: Venkatesh Pallipadi LKML-Reference: <1296694975.4418.402.camel@sbsiddha-MOBL3.sc.intel.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mtrr/main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 01c0f3ee6cc3..bebabec5b448 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -793,13 +793,21 @@ void set_mtrr_aps_delayed_init(void) } /* - * MTRR initialization for all AP's + * Delayed MTRR initialization for all AP's */ void mtrr_aps_init(void) { if (!use_intel()) return; + /* + * Check if someone has requested the delay of AP MTRR initialization, + * by doing set_mtrr_aps_delayed_init(), prior to this point. If not, + * then we are done. + */ + if (!mtrr_aps_delayed_init) + return; + set_mtrr(~0U, 0, 0, 0); mtrr_aps_delayed_init = false; } -- cgit v1.2.3 From 6adc3af5842abe628c282baf122a9be81d854b47 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Thu, 10 Feb 2011 08:50:41 +0000 Subject: fix jiffy calculations in calibrate_delay_direct to handle overflow commit 70a062286b9dfcbd24d2e11601aecfead5cf709a upstream. Fixes a hang when booting as dom0 under Xen, when jiffies can be quite large by the time the kernel init gets this far. Signed-off-by: Tim Deegan Signed-off-by: Andi Kleen [jbeulich@novell.com: !time_after() -> time_before_eq() as suggested by Jiri Slaby] Signed-off-by: Jan Beulich Cc: Jiri Slaby Cc: Jeremy Fitzhardinge Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- init/calibrate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/init/calibrate.c b/init/calibrate.c index 6eb48e53d61c..24fe022c55f9 100644 --- a/init/calibrate.c +++ b/init/calibrate.c @@ -66,7 +66,7 @@ static unsigned long __cpuinit calibrate_delay_direct(void) pre_start = 0; read_current_timer(&start); start_jiffies = jiffies; - while (jiffies <= (start_jiffies + 1)) { + while (time_before_eq(jiffies, start_jiffies + 1)) { pre_start = start; read_current_timer(&start); } @@ -74,8 +74,8 @@ static unsigned long __cpuinit calibrate_delay_direct(void) pre_end = 0; end = post_start; - while (jiffies <= - (start_jiffies + 1 + DELAY_CALIBRATION_TICKS)) { + while (time_before_eq(jiffies, start_jiffies + 1 + + DELAY_CALIBRATION_TICKS)) { pre_end = end; read_current_timer(&end); } -- cgit v1.2.3 From d9ad11a63585b0f918d396176c528e57bac99f5e Mon Sep 17 00:00:00 2001 From: Dario Lombardo Date: Fri, 21 Jan 2011 15:35:19 +0100 Subject: drivers: update to pl2303 usb-serial to support Motorola cables commit 96a3e79edff6f41b0f115a82f1a39d66218077a7 upstream. Added 0x0307 device id to support Motorola cables to the pl2303 usb serial driver. This cable has a modified chip that is a pl2303, but declares itself as 0307. Fixed by adding the right device id to the supported devices list, assigning it the code labeled PL2303_PRODUCT_ID_MOTOROLA. Signed-off-by: Dario Lombardo Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/pl2303.c | 1 + drivers/usb/serial/pl2303.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 3d619e4086df..2fcc54ef04f9 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -50,6 +50,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 43eb9bdad422..1b025f75dafd 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -21,6 +21,7 @@ #define PL2303_PRODUCT_ID_MMX 0x0612 #define PL2303_PRODUCT_ID_GPRS 0x0609 #define PL2303_PRODUCT_ID_HCR331 0x331a +#define PL2303_PRODUCT_ID_MOTOROLA 0x0307 #define ATEN_VENDOR_ID 0x0557 #define ATEN_VENDOR_ID2 0x0547 -- cgit v1.2.3 From df73343c660da9b988c068456d2ef0d511456573 Mon Sep 17 00:00:00 2001 From: David Miller Date: Sun, 13 Feb 2011 16:37:07 -0800 Subject: klist: Fix object alignment on 64-bit. commit 795abaf1e4e188c4171e3cd3dbb11a9fcacaf505 upstream. Commit c0e69a5bbc6f ("klist.c: bit 0 in pointer can't be used as flag") intended to make sure that all klist objects were at least pointer size aligned, but used the constant "4" which only works on 32-bit. Use "sizeof(void *)" which is correct in all cases. Signed-off-by: David S. Miller Acked-by: Jesper Nilsson Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/linux/klist.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/klist.h b/include/linux/klist.h index e91a4e59b771..a370ce57cf1d 100644 --- a/include/linux/klist.h +++ b/include/linux/klist.h @@ -22,7 +22,7 @@ struct klist { struct list_head k_list; void (*get)(struct klist_node *); void (*put)(struct klist_node *); -} __attribute__ ((aligned (4))); +} __attribute__ ((aligned (sizeof(void *)))); #define KLIST_INIT(_name, _get, _put) \ { .k_lock = __SPIN_LOCK_UNLOCKED(_name.k_lock), \ -- cgit v1.2.3 From e6acb2773a21f1863cf3a7a6831e4a0c2d926011 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 20 Jan 2011 20:35:23 +0000 Subject: powerpc: Fix some 6xx/7xxx CPU setup functions commit 1f1936ff3febf38d582177ea319eaa278f32c91f upstream. Some of those functions try to adjust the CPU features, for example to remove NAP support on some revisions. However, they seem to use r5 as an index into the CPU table entry, which might have been right a long time ago but no longer is. r4 is the right register to use. This probably caused some off behaviours on some PowerMac variants using 750cx or 7455 processor revisions. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/powerpc/kernel/cpu_setup_6xx.S | 40 ++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S index 55cba4a8a959..f8cd9fba4d35 100644 --- a/arch/powerpc/kernel/cpu_setup_6xx.S +++ b/arch/powerpc/kernel/cpu_setup_6xx.S @@ -18,7 +18,7 @@ #include _GLOBAL(__setup_cpu_603) - mflr r4 + mflr r5 BEGIN_MMU_FTR_SECTION li r10,0 mtspr SPRN_SPRG_603_LRU,r10 /* init SW LRU tracking */ @@ -27,60 +27,60 @@ BEGIN_FTR_SECTION bl __init_fpu_registers END_FTR_SECTION_IFCLR(CPU_FTR_FPU_UNAVAILABLE) bl setup_common_caches - mtlr r4 + mtlr r5 blr _GLOBAL(__setup_cpu_604) - mflr r4 + mflr r5 bl setup_common_caches bl setup_604_hid0 - mtlr r4 + mtlr r5 blr _GLOBAL(__setup_cpu_750) - mflr r4 + mflr r5 bl __init_fpu_registers bl setup_common_caches bl setup_750_7400_hid0 - mtlr r4 + mtlr r5 blr _GLOBAL(__setup_cpu_750cx) - mflr r4 + mflr r5 bl __init_fpu_registers bl setup_common_caches bl setup_750_7400_hid0 bl setup_750cx - mtlr r4 + mtlr r5 blr _GLOBAL(__setup_cpu_750fx) - mflr r4 + mflr r5 bl __init_fpu_registers bl setup_common_caches bl setup_750_7400_hid0 bl setup_750fx - mtlr r4 + mtlr r5 blr _GLOBAL(__setup_cpu_7400) - mflr r4 + mflr r5 bl __init_fpu_registers bl setup_7400_workarounds bl setup_common_caches bl setup_750_7400_hid0 - mtlr r4 + mtlr r5 blr _GLOBAL(__setup_cpu_7410) - mflr r4 + mflr r5 bl __init_fpu_registers bl setup_7410_workarounds bl setup_common_caches bl setup_750_7400_hid0 li r3,0 mtspr SPRN_L2CR2,r3 - mtlr r4 + mtlr r5 blr _GLOBAL(__setup_cpu_745x) - mflr r4 + mflr r5 bl setup_common_caches bl setup_745x_specifics - mtlr r4 + mtlr r5 blr /* Enable caches for 603's, 604, 750 & 7400 */ @@ -194,10 +194,10 @@ setup_750cx: cror 4*cr0+eq,4*cr0+eq,4*cr1+eq cror 4*cr0+eq,4*cr0+eq,4*cr2+eq bnelr - lwz r6,CPU_SPEC_FEATURES(r5) + lwz r6,CPU_SPEC_FEATURES(r4) li r7,CPU_FTR_CAN_NAP andc r6,r6,r7 - stw r6,CPU_SPEC_FEATURES(r5) + stw r6,CPU_SPEC_FEATURES(r4) blr /* 750fx specific @@ -225,12 +225,12 @@ BEGIN_FTR_SECTION andis. r11,r11,L3CR_L3E@h beq 1f END_FTR_SECTION_IFSET(CPU_FTR_L3CR) - lwz r6,CPU_SPEC_FEATURES(r5) + lwz r6,CPU_SPEC_FEATURES(r4) andi. r0,r6,CPU_FTR_L3_DISABLE_NAP beq 1f li r7,CPU_FTR_CAN_NAP andc r6,r6,r7 - stw r6,CPU_SPEC_FEATURES(r5) + stw r6,CPU_SPEC_FEATURES(r4) 1: mfspr r11,SPRN_HID0 -- cgit v1.2.3 From f1127642d5214684a533ba465bb62f013c51fe99 Mon Sep 17 00:00:00 2001 From: Guy Martin Date: Mon, 6 Dec 2010 16:48:04 +0100 Subject: parisc : Remove broken line wrapping handling pdc_iodc_print() commit fbea668498e93bb38ac9226c7af9120a25957375 upstream. Remove the broken line wrapping handling in pdc_iodc_print(). It is broken in 3 ways : - It doesn't keep track of the current screen position, it just assumes that the new buffer will be printed at the begining of the screen. - It doesn't take in account that non printable characters won't increase the current position on the screen. - And last but not least, it triggers a kernel panic if a backspace is the first char in the provided buffer : Backtrace: [<0000000040128ec4>] pdc_console_write+0x44/0x78 [<0000000040128f18>] pdc_console_tty_write+0x20/0x38 [<000000004032f1ac>] n_tty_write+0x2a4/0x550 [<000000004032b158>] tty_write+0x1e0/0x2d8 [<00000000401bb420>] vfs_write+0xb8/0x188 [<00000000401bb630>] sys_write+0x68/0xb8 [<0000000040104eb8>] syscall_exit+0x0/0x14 Most terminals handle the line wrapping just fine. I've confirmed that it works correctly on a C8000 with both vga and serial output. Signed-off-by: Guy Martin Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/parisc/kernel/firmware.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index df971fa0c32f..4896ed090585 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c @@ -1126,15 +1126,13 @@ int pdc_iodc_print(const unsigned char *str, unsigned count) unsigned int i; unsigned long flags; - for (i = 0; i < count && i < 79;) { + for (i = 0; i < count;) { switch(str[i]) { case '\n': iodc_dbuf[i+0] = '\r'; iodc_dbuf[i+1] = '\n'; i += 2; goto print; - case '\b': /* BS */ - i--; /* overwrite last */ default: iodc_dbuf[i] = str[i]; i++; @@ -1142,15 +1140,6 @@ int pdc_iodc_print(const unsigned char *str, unsigned count) } } - /* if we're at the end of line, and not already inserting a newline, - * insert one anyway. iodc console doesn't claim to support >79 char - * lines. don't account for this in the return value. - */ - if (i == 79 && iodc_dbuf[i-1] != '\n') { - iodc_dbuf[i+0] = '\r'; - iodc_dbuf[i+1] = '\n'; - } - print: spin_lock_irqsave(&pdc_lock, flags); real32_call(PAGE0->mem_cons.iodc_io, -- cgit v1.2.3 From e9873656fb0e28d4f5f461a990e4885e2a01f947 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Thu, 20 Jan 2011 14:44:33 -0800 Subject: kernel/smp.c: fix smp_call_function_many() SMP race commit 6dc19899958e420a931274b94019e267e2396d3e upstream. I noticed a failure where we hit the following WARN_ON in generic_smp_call_function_interrupt: if (!cpumask_test_and_clear_cpu(cpu, data->cpumask)) continue; data->csd.func(data->csd.info); refs = atomic_dec_return(&data->refs); WARN_ON(refs < 0); <------------------------- We atomically tested and cleared our bit in the cpumask, and yet the number of cpus left (ie refs) was 0. How can this be? It turns out commit 54fdade1c3332391948ec43530c02c4794a38172 ("generic-ipi: make struct call_function_data lockless") is at fault. It removes locking from smp_call_function_many and in doing so creates a rather complicated race. The problem comes about because: - The smp_call_function_many interrupt handler walks call_function.queue without any locking. - We reuse a percpu data structure in smp_call_function_many. - We do not wait for any RCU grace period before starting the next smp_call_function_many. Imagine a scenario where CPU A does two smp_call_functions back to back, and CPU B does an smp_call_function in between. We concentrate on how CPU C handles the calls: CPU A CPU B CPU C CPU D smp_call_function smp_call_function_interrupt walks call_function.queue sees data from CPU A on list smp_call_function smp_call_function_interrupt walks call_function.queue sees (stale) CPU A on list smp_call_function int clears last ref on A list_del_rcu, unlock smp_call_function reuses percpu *data A data->cpumask sees and clears bit in cpumask might be using old or new fn! decrements refs below 0 set data->refs (too late!) The important thing to note is since the interrupt handler walks a potentially stale call_function.queue without any locking, then another cpu can view the percpu *data structure at any time, even when the owner is in the process of initialising it. The following test case hits the WARN_ON 100% of the time on my PowerPC box (having 128 threads does help :) #include #include #define ITERATIONS 100 static void do_nothing_ipi(void *dummy) { } static void do_ipis(struct work_struct *dummy) { int i; for (i = 0; i < ITERATIONS; i++) smp_call_function(do_nothing_ipi, NULL, 1); printk(KERN_DEBUG "cpu %d finished\n", smp_processor_id()); } static struct work_struct work[NR_CPUS]; static int __init testcase_init(void) { int cpu; for_each_online_cpu(cpu) { INIT_WORK(&work[cpu], do_ipis); schedule_work_on(cpu, &work[cpu]); } return 0; } static void __exit testcase_exit(void) { } module_init(testcase_init) module_exit(testcase_exit) MODULE_LICENSE("GPL"); MODULE_AUTHOR("Anton Blanchard"); I tried to fix it by ordering the read and the write of ->cpumask and ->refs. In doing so I missed a critical case but Paul McKenney was able to spot my bug thankfully :) To ensure we arent viewing previous iterations the interrupt handler needs to read ->refs then ->cpumask then ->refs _again_. Thanks to Milton Miller and Paul McKenney for helping to debug this issue. [miltonm@bga.com: add WARN_ON and BUG_ON, remove extra read of refs before initial read of mask that doesn't help (also noted by Peter Zijlstra), adjust comments, hopefully clarify scenario ] [miltonm@bga.com: remove excess tests] Signed-off-by: Anton Blanchard Signed-off-by: Milton Miller Signed-off-by: Andi Kleen Cc: Ingo Molnar Cc: "Paul E. McKenney" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/smp.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/kernel/smp.c b/kernel/smp.c index 75c970c715d3..3812b02f9e85 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -194,6 +194,24 @@ void generic_smp_call_function_interrupt(void) list_for_each_entry_rcu(data, &call_function.queue, csd.list) { int refs; + /* + * Since we walk the list without any locks, we might + * see an entry that was completed, removed from the + * list and is in the process of being reused. + * + * We must check that the cpu is in the cpumask before + * checking the refs, and both must be set before + * executing the callback on this cpu. + */ + + if (!cpumask_test_cpu(cpu, data->cpumask)) + continue; + + smp_rmb(); + + if (atomic_read(&data->refs) == 0) + continue; + if (!cpumask_test_and_clear_cpu(cpu, data->cpumask)) continue; @@ -442,11 +460,21 @@ void smp_call_function_many(const struct cpumask *mask, data = &__get_cpu_var(cfd_data); csd_lock(&data->csd); + BUG_ON(atomic_read(&data->refs) || !cpumask_empty(data->cpumask)); data->csd.func = func; data->csd.info = info; cpumask_and(data->cpumask, mask, cpu_online_mask); cpumask_clear_cpu(this_cpu, data->cpumask); + + /* + * To ensure the interrupt handler gets an complete view + * we order the cpumask and refs writes and order the read + * of them in the interrupt handler. In addition we may + * only clear our own cpu bit from the mask. + */ + smp_wmb(); + atomic_set(&data->refs, cpumask_weight(data->cpumask)); raw_spin_lock_irqsave(&call_function.lock, flags); -- cgit v1.2.3 From 755fc62c61ab748285ef5940f6a7c9b93f1b70b8 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 10 Jan 2011 12:56:05 +0100 Subject: hostap_cs: fix sleeping function called from invalid context commit 4e5518ca53be29c1ec3c00089c97bef36bfed515 upstream. pcmcia_request_irq() and pcmcia_enable_device() are intended to be called from process context (first function allocate memory with GFP_KERNEL, second take a mutex). We can not take spin lock and call them. It's safe to move spin lock after pcmcia_enable_device() as we still hold off IRQ until dev->base_addr is 0 and driver will not proceed with interrupts when is not ready. Patch resolves: https://bugzilla.redhat.com/show_bug.cgi?id=643758 Reported-and-tested-by: rbugz@biobind.com Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/hostap/hostap_cs.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 29b31a694b59..357da816f086 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -626,15 +626,9 @@ static int prism2_config(struct pcmcia_device *link) local->hw_priv = hw_priv; hw_priv->link = link; - /* - * Make sure the IRQ handler cannot proceed until at least - * dev->base_addr is initialized. - */ - spin_lock_irqsave(&local->irq_init_lock, flags); - ret = pcmcia_request_irq(link, prism2_interrupt); if (ret) - goto failed_unlock; + goto failed; /* * This actually configures the PCMCIA socket -- setting up @@ -643,11 +637,12 @@ static int prism2_config(struct pcmcia_device *link) */ ret = pcmcia_request_configuration(link, &link->conf); if (ret) - goto failed_unlock; + goto failed; + /* IRQ handler cannot proceed until at dev->base_addr is initialized */ + spin_lock_irqsave(&local->irq_init_lock, flags); dev->irq = link->irq; dev->base_addr = link->io.BasePort1; - spin_unlock_irqrestore(&local->irq_init_lock, flags); /* Finally, report what we've done */ @@ -676,8 +671,6 @@ static int prism2_config(struct pcmcia_device *link) return ret; - failed_unlock: - spin_unlock_irqrestore(&local->irq_init_lock, flags); failed: kfree(hw_priv); prism2_release((u_long)link); -- cgit v1.2.3 From 863591babfdd78d107f54d0b3cff1c55841f902b Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 12 Jan 2011 09:03:35 +1100 Subject: md: fix regression with re-adding devices to arrays with no metadata commit bf572541ab44240163eaa2d486b06f306a31d45a upstream. Commit 1a855a0606 (2.6.37-rc4) fixed a problem where devices were re-added when they shouldn't be but caused a regression in a less common case that means sometimes devices cannot be re-added when they should be. In particular, when re-adding a device to an array without metadata we should always access the device, but after the above commit we didn't. This patch sets the In_sync flag in that case so that the re-add succeeds. This patch is suitable for any -stable kernel to which 1a855a0606 was applied. Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/md/md.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index db6552ca890c..605166b0ed2f 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5109,9 +5109,10 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) /* set saved_raid_disk if appropriate */ if (!mddev->persistent) { if (info->state & (1<raid_disk < mddev->raid_disks) + info->raid_disk < mddev->raid_disks) { rdev->raid_disk = info->raid_disk; - else + set_bit(In_sync, &rdev->flags); + } else rdev->raid_disk = -1; } else super_types[mddev->major_version]. -- cgit v1.2.3 From 41922ad4ddb29e0dff33a645d4d697895acb14ce Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 9 Jan 2011 17:48:20 -0500 Subject: pata_mpc52xx: inherit from ata_bmdma_port_ops commit 77c5fd19075d299fe820bb59bb21b0b113676e20 upstream. pata_mpc52xx supports BMDMA but inherits ata_sff_port_ops which triggers BUG_ON() when a DMA command is issued. Fix it. Signed-off-by: Tejun Heo Signed-off-by: Andi Kleen Reported-by: Roman Fietze Cc: Sergei Shtylyov Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/pata_mpc52xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index f087ab55b1df..8f56ef69f4db 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c @@ -610,7 +610,7 @@ static struct scsi_host_template mpc52xx_ata_sht = { }; static struct ata_port_operations mpc52xx_ata_port_ops = { - .inherits = &ata_sff_port_ops, + .inherits = &ata_bmdma_port_ops, .sff_dev_select = mpc52xx_ata_dev_select, .set_piomode = mpc52xx_ata_set_piomode, .set_dmamode = mpc52xx_ata_set_dmamode, -- cgit v1.2.3 From fdd7c779cc992bd5d0930e381b8023907cb750f0 Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Fri, 12 Nov 2010 22:30:02 +0100 Subject: TPM: Long default timeout fix commit c4ff4b829ef9e6353c0b133b7adb564a68054979 upstream. If duration variable value is 0 at this point, it's because chip->vendor.duration wasn't filled by tpm_get_timeouts() yet. This patch sets then the lowest timeout just to give enough time for tpm_get_timeouts() to further succeed. This fix avoids long boot times in case another entity attempts to send commands to the TPM when the TPM isn't accessible. Signed-off-by: Rajiv Andrade Signed-off-by: James Morris Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/char/tpm/tpm.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 05ad4a17a28f..4baed0f9485d 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -354,12 +354,14 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, tpm_protected_ordinal_duration[ordinal & TPM_PROTECTED_ORDINAL_MASK]; - if (duration_idx != TPM_UNDEFINED) + if (duration_idx != TPM_UNDEFINED) { duration = chip->vendor.duration[duration_idx]; - if (duration <= 0) + /* if duration is 0, it's because chip->vendor.duration wasn't */ + /* filled yet, so we set the lowest timeout just to give enough */ + /* time for tpm_get_timeouts() to succeed */ + return (duration <= 0 ? HZ : duration); + } else return 2 * 60 * HZ; - else - return duration; } EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); -- cgit v1.2.3 From 5373abb7b877203095f9bd806d9f8040998fccb5 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Tue, 11 Jan 2011 14:37:29 -0500 Subject: tpm_tis: Use timeouts returned from TPM commit 9b29050f8f75916f974a2d231ae5d3cd59792296 upstream. The current TPM TIS driver in git discards the timeout values returned from the TPM. The check of the response packet needs to consider that the return_code field is 0 on success and the size of the expected packet is equivalent to the header size + u32 length indicator for the TPM_GetCapability() result + 3 timeout indicators of type u32. I am also adding a sysfs entry 'timeouts' showing the timeouts that are being used. Signed-off-by: Stefan Berger Signed-off-by: Andi Kleen Tested-by: Guillaume Chazarain Signed-off-by: Rajiv Andrade Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm.c | 18 ++++++++++++++++-- drivers/char/tpm/tpm.h | 2 ++ drivers/char/tpm/tpm_tis.c | 4 +++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 4baed0f9485d..2ec5f33cdbd0 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -567,9 +567,11 @@ duration: if (rc) return; - if (be32_to_cpu(tpm_cmd.header.out.return_code) - != 3 * sizeof(u32)) + if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || + be32_to_cpu(tpm_cmd.header.out.length) + != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32)) return; + duration_cap = &tpm_cmd.params.getcap_out.cap.duration; chip->vendor.duration[TPM_SHORT] = usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short)); @@ -913,6 +915,18 @@ ssize_t tpm_show_caps_1_2(struct device * dev, } EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); +ssize_t tpm_show_timeouts(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tpm_chip *chip = dev_get_drvdata(dev); + + return sprintf(buf, "%d %d %d\n", + jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]), + jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]), + jiffies_to_usecs(chip->vendor.duration[TPM_LONG])); +} +EXPORT_SYMBOL_GPL(tpm_show_timeouts); + ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 792868d24f2a..ba1779c2cffd 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -56,6 +56,8 @@ extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr, char *); extern ssize_t tpm_show_temp_deactivated(struct device *, struct device_attribute *attr, char *); +extern ssize_t tpm_show_timeouts(struct device *, + struct device_attribute *attr, char *); struct tpm_chip; diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 1030f8420137..ef9c4acf88e4 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -355,6 +355,7 @@ static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL); static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); +static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL); static struct attribute *tis_attrs[] = { &dev_attr_pubek.attr, @@ -364,7 +365,8 @@ static struct attribute *tis_attrs[] = { &dev_attr_owned.attr, &dev_attr_temp_deactivated.attr, &dev_attr_caps.attr, - &dev_attr_cancel.attr, NULL, + &dev_attr_cancel.attr, + &dev_attr_timeouts.attr, NULL, }; static struct attribute_group tis_attr_grp = { -- cgit v1.2.3 From 88164580062e2fcb5afe58cd7ffaca05f668f009 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 16 Dec 2010 11:46:51 -0500 Subject: SELinux: define permissions for DCB netlink messages commit 350e4f31e0eaf56dfc3b328d24a11bdf42a41fb8 upstream. Commit 2f90b865 added two new netlink message types to the netlink route socket. SELinux has hooks to define if netlink messages are allowed to be sent or received, but it did not know about these two new message types. By default we allow such actions so noone likely noticed. This patch adds the proper definitions and thus proper permissions enforcement. Signed-off-by: Eric Paris Signed-off-by: Andi Kleen Cc: James Morris Signed-off-by: Greg Kroah-Hartman --- security/selinux/nlmsgtab.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 75ec0c6ebacd..8b02b2137da2 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c @@ -65,6 +65,8 @@ static struct nlmsg_perm nlmsg_route_perms[] = { RTM_NEWADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, { RTM_DELADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, { RTM_GETADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_READ }, + { RTM_GETDCB, NETLINK_ROUTE_SOCKET__NLMSG_READ }, + { RTM_SETDCB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, }; static struct nlmsg_perm nlmsg_firewall_perms[] = -- cgit v1.2.3 From 840533075951dd0ce6c4bfaca3182bb1dbedb230 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 2 Dec 2010 16:13:40 -0500 Subject: SELinux: do not compute transition labels on mountpoint labeled filesystems commit 415103f9932d45f7927f4b17e3a9a13834cdb9a1 upstream. selinux_inode_init_security computes transitions sids even for filesystems that use mount point labeling. It shouldn't do that. It should just use the mount point label always and no matter what. This causes 2 problems. 1) it makes file creation slower than it needs to be since we calculate the transition sid and 2) it allows files to be created with a different label than the mount point! # id -Z staff_u:sysadm_r:sysadm_t:s0-s0:c0.c1023 # sesearch --type --class file --source sysadm_t --target tmp_t Found 1 semantic te rules: type_transition sysadm_t tmp_t : file user_tmp_t; # mount -o loop,context="system_u:object_r:tmp_t:s0" /tmp/fs /mnt/tmp # ls -lZ /mnt/tmp drwx------. root root system_u:object_r:tmp_t:s0 lost+found # touch /mnt/tmp/file1 # ls -lZ /mnt/tmp -rw-r--r--. root root staff_u:object_r:user_tmp_t:s0 file1 drwx------. root root system_u:object_r:tmp_t:s0 lost+found Whoops, we have a mount point labeled filesystem tmp_t with a user_tmp_t labeled file! Signed-off-by: Eric Paris Signed-off-by: Andi Kleen Reviewed-by: Reviewed-by: James Morris Signed-off-by: Greg Kroah-Hartman --- security/selinux/hooks.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5c9f25ba1c95..49e55c041fa8 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2573,7 +2573,10 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, sid = tsec->sid; newsid = tsec->create_sid; - if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { + if ((sbsec->flags & SE_SBINITIALIZED) && + (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) + newsid = sbsec->mntpoint_sid; + else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { rc = security_transition_sid(sid, dsec->sid, inode_mode_to_security_class(inode->i_mode), &newsid); -- cgit v1.2.3 From 7aa043b04c3584f52c9c3e120fca1521d8836499 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Tue, 11 Jan 2011 16:14:24 -0800 Subject: ieee80211: correct IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK macro commit 8d661f1e462d50bd83de87ee628aaf820ce3c66c upstream. It is defined in include/linux/ieee80211.h. As per IEEE spec. bit6 to bit15 in block ack parameter represents buffer size. So the bitmask should be 0xFFC0. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: Andi Kleen Reviewed-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- include/linux/ieee80211.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 97b2eae6a22c..731854ccb840 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -959,7 +959,7 @@ struct ieee80211_ht_info { /* block-ack parameters */ #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 #define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C -#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0 +#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFC0 #define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 #define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 -- cgit v1.2.3 From 909e776f2916d9197efd789d52c9f34c41415453 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Thu, 13 Jan 2011 19:53:46 +0000 Subject: dm: dont take i_mutex to change device size commit c217649bf2d60ac119afd71d938278cffd55962b upstream. No longer needlessly hold md->bdev->bd_inode->i_mutex when changing the size of a DM device. This additional locking is unnecessary because i_size_write() is already protected by the existing critical section in dm_swap_table(). DM already has a reference on md->bdev so the associated bd_inode may be changed without lifetime concerns. A negative side-effect of having held md->bdev->bd_inode->i_mutex was that a concurrent DM device resize and flush (via fsync) would deadlock. Dropping md->bdev->bd_inode->i_mutex eliminates this potential for deadlock. The following reproducer no longer deadlocks: https://www.redhat.com/archives/dm-devel/2009-July/msg00284.html Signed-off-by: Mike Snitzer Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/md/dm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index e3a512dc593a..96f01d250612 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -2040,13 +2040,14 @@ static void event_callback(void *context) wake_up(&md->eventq); } +/* + * Protected by md->suspend_lock obtained by dm_swap_table(). + */ static void __set_size(struct mapped_device *md, sector_t size) { set_capacity(md->disk, size); - mutex_lock(&md->bdev->bd_inode->i_mutex); i_size_write(md->bdev->bd_inode, (loff_t)size << SECTOR_SHIFT); - mutex_unlock(&md->bdev->bd_inode->i_mutex); } /* -- cgit v1.2.3 From 940da4c89846182301e4cef616f62e921a979369 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Thu, 13 Jan 2011 19:59:46 +0000 Subject: dm mpath: disable blk_abort_queue commit 09c9d4c9b6a2b5909ae3c6265e4cd3820b636863 upstream. Revert commit 224cb3e981f1b2f9f93dbd49eaef505d17d894c2 dm: Call blk_abort_queue on failed paths Multipath began to use blk_abort_queue() to allow for lower latency path deactivation. This was found to cause list corruption: the cmd gets blk_abort_queued/timedout run on it and the scsi eh somehow is able to complete and run scsi_queue_insert while scsi_request_fn is still trying to process the request. https://www.redhat.com/archives/dm-devel/2010-November/msg00085.html Signed-off-by: Mike Snitzer Signed-off-by: Alasdair G Kergon Signed-off-by: Andi Kleen Cc: Mike Anderson Cc: Mike Christie Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-mpath.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 826bce7343b3..b294ea6d4f62 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -33,7 +33,6 @@ struct pgpath { unsigned fail_count; /* Cumulative failure count */ struct dm_path path; - struct work_struct deactivate_path; struct work_struct activate_path; }; @@ -116,7 +115,6 @@ static struct workqueue_struct *kmultipathd, *kmpath_handlerd; static void process_queued_ios(struct work_struct *work); static void trigger_event(struct work_struct *work); static void activate_path(struct work_struct *work); -static void deactivate_path(struct work_struct *work); /*----------------------------------------------- @@ -129,7 +127,6 @@ static struct pgpath *alloc_pgpath(void) if (pgpath) { pgpath->is_active = 1; - INIT_WORK(&pgpath->deactivate_path, deactivate_path); INIT_WORK(&pgpath->activate_path, activate_path); } @@ -141,14 +138,6 @@ static void free_pgpath(struct pgpath *pgpath) kfree(pgpath); } -static void deactivate_path(struct work_struct *work) -{ - struct pgpath *pgpath = - container_of(work, struct pgpath, deactivate_path); - - blk_abort_queue(pgpath->path.dev->bdev->bd_disk->queue); -} - static struct priority_group *alloc_priority_group(void) { struct priority_group *pg; @@ -993,7 +982,6 @@ static int fail_path(struct pgpath *pgpath) pgpath->path.dev->name, m->nr_valid_paths); schedule_work(&m->trigger_event); - queue_work(kmultipathd, &pgpath->deactivate_path); out: spin_unlock_irqrestore(&m->lock, flags); -- cgit v1.2.3 From 56da787c4103bae08b51d52de36c18a3daf0e338 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 4 Jan 2011 00:43:39 -0500 Subject: drm/radeon/kms: add quirk for Mac Radeon HD 2600 card MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f598aa7593427ffe3a61e7767c34bd695a5e7ed0 upstream. Reported-by: 屋国遥 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/radeon_atombios.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 42d876a5751b..ce3f0e4b7b19 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -289,6 +289,17 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, *line_mux = 0x90; } + /* mac rv630 */ + if ((dev->pdev->device == 0x9588) && + (dev->pdev->subsystem_vendor == 0x106b) && + (dev->pdev->subsystem_device == 0x00a6)) { + if ((supported_device == ATOM_DEVICE_TV1_SUPPORT) && + (*connector_type == DRM_MODE_CONNECTOR_DVII)) { + *connector_type = DRM_MODE_CONNECTOR_9PinDIN; + *line_mux = CONNECTOR_7PIN_DIN_ENUM_ID1; + } + } + /* ASUS HD 3600 XT board lists the DVI port as HDMI */ if ((dev->pdev->device == 0x9598) && (dev->pdev->subsystem_vendor == 0x1043) && -- cgit v1.2.3 From 083c5885f631f3694246fceee32ee2cb77192a8c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 18 Jan 2011 18:26:11 +0000 Subject: drm/radeon/kms: make the mac rv630 quirk generic commit be23da8ad219650517cbbb7acbeaeb235667113a upstream. Seems some other boards do this as well. Reported-by: Andrea Merello Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/radeon_atombios.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index ce3f0e4b7b19..ce958b908c13 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -289,15 +289,11 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, *line_mux = 0x90; } - /* mac rv630 */ - if ((dev->pdev->device == 0x9588) && - (dev->pdev->subsystem_vendor == 0x106b) && - (dev->pdev->subsystem_device == 0x00a6)) { - if ((supported_device == ATOM_DEVICE_TV1_SUPPORT) && - (*connector_type == DRM_MODE_CONNECTOR_DVII)) { - *connector_type = DRM_MODE_CONNECTOR_9PinDIN; - *line_mux = CONNECTOR_7PIN_DIN_ENUM_ID1; - } + /* mac rv630, rv730, others */ + if ((supported_device == ATOM_DEVICE_TV1_SUPPORT) && + (*connector_type == DRM_MODE_CONNECTOR_DVII)) { + *connector_type = DRM_MODE_CONNECTOR_9PinDIN; + *line_mux = CONNECTOR_7PIN_DIN_ENUM_ID1; } /* ASUS HD 3600 XT board lists the DVI port as HDMI */ -- cgit v1.2.3 From 534db03998f262ce3dd832948adb5309a45af6ed Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 31 Jan 2011 16:48:51 -0500 Subject: drm/radeon/kms: add pll debugging output commit 51d4bf840a27fe02c883ddc6d9708af056773769 upstream. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/radeon_display.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 2d95376c3ddf..ce627b2b9dce 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -619,6 +619,10 @@ static void radeon_compute_pll_legacy(struct radeon_pll *pll, *frac_fb_div_p = best_frac_feedback_div; *ref_div_p = best_ref_div; *post_div_p = best_post_div; + DRM_DEBUG_KMS("%d %d, pll dividers - fb: %d.%d ref: %d, post %d\n", + freq, best_freq / 1000, best_feedback_div, best_frac_feedback_div, + best_ref_div, best_post_div); + } static bool -- cgit v1.2.3 From 18021895811ff8556c0dfe5bed81ef90d053340c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 1 Feb 2011 19:06:46 -0500 Subject: drm/radeon: remove 0x4243 pci id commit 63a507800c8aca5a1891d598ae13f829346e8e39 upstream. 0x4243 is a PCI bridge, not a GPU. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=33815 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/drm/drm_pciids.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 883c1d439899..40b1f0e14963 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -28,7 +28,6 @@ {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP}, \ {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ -- cgit v1.2.3 From 06d8e2516efb9e1574135d42cee2626e27961652 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 2 Feb 2011 19:46:06 -0500 Subject: drm/radeon/kms: fix s/r issues with bios scratch regs commit 87364760de5d631390c478fcbac8db1b926e0adf upstream. The accelerate mode bit gets checked by certain atom command tables to set up some register state. It needs to be clear when setting modes and set when not. Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=26942 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/radeon_atombios.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index ce958b908c13..f8dc72da3238 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -2125,7 +2125,7 @@ void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) bios_2_scratch &= ~ATOM_S2_VRI_BRIGHT_ENABLE; /* tell the bios not to handle mode switching */ - bios_6_scratch |= (ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH | ATOM_S6_ACC_MODE); + bios_6_scratch |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH; if (rdev->family >= CHIP_R600) { WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch); @@ -2176,10 +2176,13 @@ void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock) else bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); - if (lock) + if (lock) { bios_6_scratch |= ATOM_S6_CRITICAL_STATE; - else + bios_6_scratch &= ~ATOM_S6_ACC_MODE; + } else { bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE; + bios_6_scratch |= ATOM_S6_ACC_MODE; + } if (rdev->family >= CHIP_R600) WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch); -- cgit v1.2.3 From 47cf86927073a10323fa5ce198adba1ce69b3748 Mon Sep 17 00:00:00 2001 From: Knut Petersen Date: Fri, 14 Jan 2011 15:38:10 +0000 Subject: drm/i915/lvds: Add AOpen i915GMm-HFS to the list of false-positive LVDS commit 22ab70d3262ddb6e69b3c246a34e2967ba5eb1e8 upstream. Signed-off-by: Knut Petersen Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/i915/intel_lvds.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 7d42ff16c4f6..1266ab39d6dd 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -809,6 +809,14 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_BOARD_NAME, "i915GMx-F"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "AOpen i915GMm-HFS", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"), + DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"), + }, + }, { .callback = intel_no_lvds_dmi_callback, .ident = "Aopen i945GTt-VFA", -- cgit v1.2.3 From fbb04f77b029c591fd77043e4c88b600efff5027 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 20 Jan 2011 10:03:24 +0000 Subject: drm/i915: Add dependency on CONFIG_TMPFS commit f7ab9b407b3bc83161c2aa74c992ba4782e87c9c upstream. Without tmpfs, shmem_readpage() is not compiled in causing an OOPS as soon as we try to allocate some swappable pages for GEM. Jan 19 22:52:26 harlie kernel: Modules linked in: i915(+) drm_kms_helper cfbcopyarea video backlight cfbimgblt cfbfillrect Jan 19 22:52:26 harlie kernel: Jan 19 22:52:26 harlie kernel: Pid: 1125, comm: modprobe Not tainted 2.6.37Harlie #10 To be filled by O.E.M./To be filled by O.E.M. Jan 19 22:52:26 harlie kernel: EIP: 0060:[<00000000>] EFLAGS: 00010246 CPU: 3 Jan 19 22:52:26 harlie kernel: EIP is at 0x0 Jan 19 22:52:26 harlie kernel: EAX: 00000000 EBX: f7b7d000 ECX: f3383100 EDX: f7b7d000 Jan 19 22:52:26 harlie kernel: ESI: f1456118 EDI: 00000000 EBP: f2303c98 ESP: f2303c7c Jan 19 22:52:26 harlie kernel: DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 Jan 19 22:52:26 harlie kernel: Process modprobe (pid: 1125, ti=f2302000 task=f259cd80 task.ti=f2302000) Jan 19 22:52:26 harlie kernel: Stack: Jan 19 22:52:26 harlie udevd-work[1072]: '/sbin/modprobe -b pci:v00008086d00000046sv00000000sd00000000bc03sc00i00' unexpected exit with status 0x0009 Jan 19 22:52:26 harlie kernel: c1074061 000000d0 f2f42b80 00000000 000a13d2 f2d5dcc0 00000001 f2303cac Jan 19 22:52:26 harlie kernel: c107416f 00000000 000a13d2 00000000 f2303cd4 f8d620ed f2cee620 00001000 Jan 19 22:52:26 harlie kernel: 00000000 000a13d2 f1456118 f2d5dcc0 f1a40000 00001000 f2303d04 f8d637ab Jan 19 22:52:26 harlie kernel: Call Trace: Jan 19 22:52:26 harlie kernel: [] ? do_read_cache_page+0x71/0x160 Jan 19 22:52:26 harlie kernel: [] ? read_cache_page_gfp+0x1f/0x30 Jan 19 22:52:26 harlie kernel: [] ? i915_gem_object_get_pages+0xad/0x1d0 [i915] Jan 19 22:52:26 harlie kernel: [] ? i915_gem_object_bind_to_gtt+0xeb/0x2d0 [i915] Jan 19 22:52:26 harlie kernel: [] ? i915_gem_object_pin+0x151/0x190 [i915] Jan 19 22:52:26 harlie kernel: [] ? drm_gem_object_init+0x3d/0x60 Jan 19 22:52:26 harlie kernel: [] ? i915_gem_init_ringbuffer+0x105/0x1e0 [i915] Jan 19 22:52:26 harlie kernel: [] ? i915_driver_load+0x667/0x1160 [i915] Reported-by: John J. Stimson-III Signed-off-by: Chris Wilson Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 88910e5a2c77..83dac281f501 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -96,7 +96,10 @@ config DRM_I830 config DRM_I915 tristate "i915 driver" depends on AGP_INTEL + # we need shmfs for the swappable backing store, and in particular + # the shmem_readpage() which depends upon tmpfs select SHMEM + select TMPFS select DRM_KMS_HELPER select FB_CFB_FILLRECT select FB_CFB_COPYAREA -- cgit v1.2.3 From e9cedc82e9ec9c15723490ea9f6daaa2806ac094 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 3 Feb 2011 12:20:04 -0800 Subject: x86, mm: avoid possible bogus tlb entries by clearing prev mm_cpumask after switching mm commit 831d52bc153971b70e64eccfbed2b232394f22f8 upstream. Clearing the cpu in prev's mm_cpumask early will avoid the flush tlb IPI's while the cr3 is still pointing to the prev mm. And this window can lead to the possibility of bogus TLB fills resulting in strange failures. One such problematic scenario is mentioned below. T1. CPU-1 is context switching from mm1 to mm2 context and got a NMI etc between the point of clearing the cpu from the mm_cpumask(mm1) and before reloading the cr3 with the new mm2. T2. CPU-2 is tearing down a specific vma for mm1 and will proceed with flushing the TLB for mm1. It doesn't send the flush TLB to CPU-1 as it doesn't see that cpu listed in the mm_cpumask(mm1). T3. After the TLB flush is complete, CPU-2 goes ahead and frees the page-table pages associated with the removed vma mapping. T4. CPU-2 now allocates those freed page-table pages for something else. T5. As the CR3 and TLB caches for mm1 is still active on CPU-1, CPU-1 can potentially speculate and walk through the page-table caches and can insert new TLB entries. As the page-table pages are already freed and being used on CPU-2, this page walk can potentially insert a bogus global TLB entry depending on the (random) contents of the page that is being used on CPU-2. T6. This bogus TLB entry being global will be active across future CR3 changes and can result in weird memory corruption etc. To avoid this issue, for the prev mm that is handing over the cpu to another mm, clear the cpu from the mm_cpumask(prev) after the cr3 is changed. Marking it for -stable, though we haven't seen any reported failure that can be attributed to this. Signed-off-by: Suresh Siddha Acked-by: Ingo Molnar Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/include/asm/mmu_context.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h index 4a2d4e0c18d9..8b5393ec1080 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h @@ -36,8 +36,6 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, unsigned cpu = smp_processor_id(); if (likely(prev != next)) { - /* stop flush ipis for the previous mm */ - cpumask_clear_cpu(cpu, mm_cpumask(prev)); #ifdef CONFIG_SMP percpu_write(cpu_tlbstate.state, TLBSTATE_OK); percpu_write(cpu_tlbstate.active_mm, next); @@ -47,6 +45,9 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, /* Re-load page tables */ load_cr3(next->pgd); + /* stop flush ipis for the previous mm */ + cpumask_clear_cpu(cpu, mm_cpumask(prev)); + /* * load the LDT, if the LDT is different: */ -- cgit v1.2.3 From 824a6dcef20b339735b0f0e89841fcf2fbbe2621 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 23 Dec 2010 11:12:42 -0800 Subject: usb: Realloc xHCI structures after a hub is verified. commit 653a39d1f61bdc9f277766736d21d2e9be0391cb upstream. When there's an xHCI host power loss after a suspend from memory, the USB core attempts to reset and verify the USB devices that are attached to the system. The xHCI driver has to reallocate those devices, since the hardware lost all knowledge of them during the power loss. When a hub is plugged in, and the host loses power, the xHCI hardware structures are not updated to say the device is a hub. This is usually done in hub_configure() when the USB hub is detected. That function is skipped during a reset and verify by the USB core, since the core restores the old configuration and alternate settings, and the hub driver has no idea this happened. This bug makes the xHCI host controller reject the enumeration of low speed devices under the resumed hub. Therefore, make the USB core re-setup the internal xHCI hub device information by calling update_hub_device() when hub_activate() is called for a hub reset resume. After a host power loss, all devices under the roothub get a reset-resume or a disconnect. This patch should be queued for the 2.6.37 stable tree. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/core/hub.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 0b156a55c5a6..d4041c627ff1 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -677,6 +677,8 @@ static void hub_init_func3(struct work_struct *ws); static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) { struct usb_device *hdev = hub->hdev; + struct usb_hcd *hcd; + int ret; int port1; int status; bool need_debounce_delay = false; @@ -715,6 +717,25 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) usb_autopm_get_interface_no_resume( to_usb_interface(hub->intfdev)); return; /* Continues at init2: below */ + } else if (type == HUB_RESET_RESUME) { + /* The internal host controller state for the hub device + * may be gone after a host power loss on system resume. + * Update the device's info so the HW knows it's a hub. + */ + hcd = bus_to_hcd(hdev->bus); + if (hcd->driver->update_hub_device) { + ret = hcd->driver->update_hub_device(hcd, hdev, + &hub->tt, GFP_NOIO); + if (ret < 0) { + dev_err(hub->intfdev, "Host not " + "accepting hub info " + "update.\n"); + dev_err(hub->intfdev, "LS/FS devices " + "and hubs may not work " + "under this hub\n."); + } + } + hub_power_on(hub, true); } else { hub_power_on(hub, true); } -- cgit v1.2.3 From 25f24a9de3c47261441bfa3d9cccae3616f42893 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Feb 2011 09:52:07 +0100 Subject: sched: Move sched_avg_update() to update_cpu_load() Commit: da2b71edd8a7db44fe1746261410a981f3e03632 upstream Currently sched_avg_update() (which updates rt_avg stats in the rq) is getting called from scale_rt_power() (in the load balance context) which doesn't take rq->lock. Fix it by moving the sched_avg_update() to more appropriate update_cpu_load() where the CFS load gets updated as well. Signed-off-by: Suresh Siddha Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <1282596171.2694.3.camel@sbsiddha-MOBL3> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 6 ++++++ kernel/sched_fair.c | 2 -- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index d4f71b01136c..1747071e26f1 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1270,6 +1270,10 @@ static void resched_task(struct task_struct *p) static void sched_rt_avg_update(struct rq *rq, u64 rt_delta) { } + +static void sched_avg_update(struct rq *rq) +{ +} #endif /* CONFIG_SMP */ #if BITS_PER_LONG == 32 @@ -3152,6 +3156,8 @@ static void update_cpu_load(struct rq *this_rq) } calc_load_account_active(this_rq); + + sched_avg_update(this_rq); } #ifdef CONFIG_SMP diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index a878b5332daa..44d7bdc800f8 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -2268,8 +2268,6 @@ unsigned long scale_rt_power(int cpu) struct rq *rq = cpu_rq(cpu); u64 total, available; - sched_avg_update(rq); - total = sched_avg_period() + (rq->clock - rq->age_stamp); available = total - rq->rt_avg; -- cgit v1.2.3 From ce2e30cac777d6969855db38f5e4f73304e27196 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Thu, 10 Feb 2011 09:52:52 +0100 Subject: sched: Increment cache_nice_tries only on periodic lb Commit: 58b26c4c025778c09c7a1438ff185080e11b7d0a upstream scheduler uses cache_nice_tries as an indicator to do cache_hot and active load balance, when normal load balance fails. Currently, this value is changed on any failed load balance attempt. That ends up being not so nice to workloads that enter/exit idle often, as they do more frequent new_idle balance and that pretty soon results in cache hot tasks being pulled in. Making the cache_nice_tries ignore failed new_idle balance seems to make better sense. With that only the failed load balance in periodic load balance gets accounted and the rate of accumulation of cache_nice_tries will not depend on idle entry/exit (short running sleep-wakeup kind of tasks). This reduces movement of cache_hot tasks. schedstat diff (after-before) excerpt from a workload that has frequent and short wakeup-idle pattern (:2 in cpu col below refers to NEWIDLE idx) This snapshot was across ~400 seconds. Without this change: domainstats: domain0 cpu cnt bln fld imb gain hgain nobusyq nobusyg 0:2 306487 219575 73167 110069413 44583 19070 1172 218403 1:2 292139 194853 81421 120893383 50745 21902 1259 193594 2:2 283166 174607 91359 129699642 54931 23688 1287 173320 3:2 273998 161788 93991 132757146 57122 24351 1366 160422 4:2 289851 215692 62190 83398383 36377 13680 851 214841 5:2 316312 222146 77605 117582154 49948 20281 988 221158 6:2 297172 195596 83623 122133390 52801 21301 929 194667 7:2 283391 178078 86378 126622761 55122 22239 928 177150 8:2 297655 210359 72995 110246694 45798 19777 1125 209234 9:2 297357 202011 79363 119753474 50953 22088 1089 200922 10:2 278797 178703 83180 122514385 52969 22726 1128 177575 11:2 272661 167669 86978 127342327 55857 24342 1195 166474 12:2 293039 204031 73211 110282059 47285 19651 948 203083 13:2 289502 196762 76803 114712942 49339 20547 1016 195746 14:2 264446 169609 78292 115715605 50459 21017 982 168627 15:2 260968 163660 80142 116811793 51483 21281 1064 162596 With this change: domainstats: domain0 cpu cnt bln fld imb gain hgain nobusyq nobusyg 0:2 272347 187380 77455 105420270 24975 1 953 186427 1:2 267276 172360 86234 116242264 28087 6 1028 171332 2:2 259769 156777 93281 123243134 30555 1 1043 155734 3:2 250870 143129 97627 127370868 32026 6 1188 141941 4:2 248422 177116 64096 78261112 22202 2 757 176359 5:2 275595 180683 84950 116075022 29400 6 778 179905 6:2 262418 162609 88944 119256898 31056 4 817 161792 7:2 252204 147946 92646 122388300 32879 4 824 147122 8:2 262335 172239 81631 110477214 26599 4 864 171375 9:2 261563 164775 88016 117203621 28331 3 849 163926 10:2 243389 140949 93379 121353071 29585 2 909 140040 11:2 242795 134651 98310 124768957 30895 2 1016 133635 12:2 255234 166622 79843 104696912 26483 4 746 165876 13:2 244944 151595 83855 109808099 27787 3 801 150794 14:2 241301 140982 89935 116954383 30403 6 845 140137 15:2 232271 128564 92821 119185207 31207 4 1416 127148 Signed-off-by: Venkatesh Pallipadi Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <1284167957-3675-1-git-send-email-venki@google.com> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- kernel/sched_fair.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 44d7bdc800f8..e71d44e5bf55 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -2894,7 +2894,14 @@ redo: if (!ld_moved) { schedstat_inc(sd, lb_failed[idle]); - sd->nr_balance_failed++; + /* + * Increment the failure counter only on periodic balance. + * We do not want newidle balance, which can be very + * frequent, pollute the failure counter causing + * excessive cache_hot migrations and active balances. + */ + if (idle != CPU_NEWLY_IDLE) + sd->nr_balance_failed++; if (need_active_balance(sd, sd_idle, idle)) { raw_spin_lock_irqsave(&busiest->lock, flags); -- cgit v1.2.3 From 758df963bb23a00cb6f2fbf9714ea37d3fa116a8 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 10 Feb 2011 10:20:08 +0100 Subject: sched: Try not to migrate higher priority RT tasks Commit: 43fa5460fe60dea5c610490a1d263415419c60f6 upstream When first working on the RT scheduler design, we concentrated on keeping all CPUs running RT tasks instead of having multiple RT tasks on a single CPU waiting for the migration thread to move them. Instead we take a more proactive stance and push or pull RT tasks from one CPU to another on wakeup or scheduling. When an RT task wakes up on a CPU that is running another RT task, instead of preempting it and killing the cache of the running RT task, we look to see if we can migrate the RT task that is waking up, even if the RT task waking up is of higher priority. This may sound a bit odd, but RT tasks should be limited in migration by the user anyway. But in practice, people do not do this, which causes high prio RT tasks to bounce around the CPUs. This becomes even worse when we have priority inheritance, because a high prio task can block on a lower prio task and boost its priority. When the lower prio task wakes up the high prio task, if it happens to be on the same CPU it will migrate off of it. But in reality, the above does not happen much either, because the wake up of the lower prio task, which has already been boosted, if it was on the same CPU as the higher prio task, it would then migrate off of it. But anyway, we do not want to migrate them either. To examine the scheduling, I created a test program and examined it under kernelshark. The test program created CPU * 2 threads, where each thread had a different priority. The program takes different options. The options used in this change log was to have priority inheritance mutexes or not. All threads did the following loop: static void grab_lock(long id, int iter, int l) { ftrace_write("thread %ld iter %d, taking lock %d\n", id, iter, l); pthread_mutex_lock(&locks[l]); ftrace_write("thread %ld iter %d, took lock %d\n", id, iter, l); busy_loop(nr_tasks - id); ftrace_write("thread %ld iter %d, unlock lock %d\n", id, iter, l); pthread_mutex_unlock(&locks[l]); } void *start_task(void *id) { [...] while (!done) { for (l = 0; l < nr_locks; l++) { grab_lock(id, i, l); ftrace_write("thread %ld iter %d sleeping\n", id, i); ms_sleep(id); } i++; } [...] } The busy_loop(ms) keeps the CPU spinning for ms milliseconds. The ms_sleep(ms) sleeps for ms milliseconds. The ftrace_write() writes to the ftrace buffer to help analyze via ftrace. The higher the id, the higher the prio, the shorter it does the busy loop, but the longer it spins. This is usually the case with RT tasks, the lower priority tasks usually run longer than higher priority tasks. At the end of the test, it records the number of loops each thread took, as well as the number of voluntary preemptions, non-voluntary preemptions, and number of migrations each thread took, taking the information from /proc/$$/sched and /proc/$$/status. Running this on a 4 CPU processor, the results without changes to the kernel looked like this: Task vol nonvol migrated iterations Signed-off-by: Andi Kleen ---- --- ------ -------- ---------- 0: 53 3220 1470 98 1: 562 773 724 98 2: 752 933 1375 98 3: 749 39 697 98 4: 758 5 515 98 5: 764 2 679 99 6: 761 2 535 99 7: 757 3 346 99 total: 5156 4977 6341 787 Each thread regardless of priority migrated a few hundred times. The higher priority tasks, were a little better but still took quite an impact. By letting higher priority tasks bump the lower prio task from the CPU, things changed a bit: Task vol nonvol migrated iterations ---- --- ------ -------- ---------- 0: 37 2835 1937 98 1: 666 1821 1865 98 2: 654 1003 1385 98 3: 664 635 973 99 4: 698 197 352 99 5: 703 101 159 99 6: 708 1 75 99 7: 713 1 2 99 total: 4843 6594 6748 789 The total # of migrations did not change (several runs showed the difference all within the noise). But we now see a dramatic improvement to the higher priority tasks. (kernelshark showed that the watchdog timer bumped the highest priority task to give it the 2 count. This was actually consistent with every run). Notice that the # of iterations did not change either. The above was with priority inheritance mutexes. That is, when the higher prority task blocked on a lower priority task, the lower priority task would inherit the higher priority task (which shows why task 6 was bumped so many times). When not using priority inheritance mutexes, the current kernel shows this: Task vol nonvol migrated iterations ---- --- ------ -------- ---------- 0: 56 3101 1892 95 1: 594 713 937 95 2: 625 188 618 95 3: 628 4 491 96 4: 640 7 468 96 5: 631 2 501 96 6: 641 1 466 96 7: 643 2 497 96 total: 4458 4018 5870 765 Not much changed with or without priority inheritance mutexes. But if we let the high priority task bump lower priority tasks on wakeup we see: Task vol nonvol migrated iterations ---- --- ------ -------- ---------- 0: 115 3439 2782 98 1: 633 1354 1583 99 2: 652 919 1218 99 3: 645 713 934 99 4: 690 3 3 99 5: 694 1 4 99 6: 720 3 4 99 7: 747 0 1 100 Which shows a even bigger change. The big difference between task 3 and task 4 is because we have only 4 CPUs on the machine, causing the 4 highest prio tasks to always have preference. Although I did not measure cache misses, and I'm sure there would be little to measure since the test was not data intensive, I could imagine large improvements for higher priority tasks when dealing with lower priority tasks. Thus, I'm satisfied with making the change and agreeing with what Gregory Haskins argued a few years ago when we first had this discussion. One final note. All tasks in the above tests were RT tasks. Any RT task will always preempt a non RT task that is running on the CPU the RT task wants to run on. Signed-off-by: Steven Rostedt Signed-off-by: Peter Zijlstra Cc: Gregory Haskins LKML-Reference: <20100921024138.605460343@goodmis.org> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- kernel/sched_rt.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 8afb953e31c6..86a2f77977c6 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -960,18 +960,18 @@ select_task_rq_rt(struct rq *rq, struct task_struct *p, int sd_flag, int flags) * runqueue. Otherwise simply start this RT task * on its current runqueue. * - * We want to avoid overloading runqueues. Even if - * the RT task is of higher priority than the current RT task. - * RT tasks behave differently than other tasks. If - * one gets preempted, we try to push it off to another queue. - * So trying to keep a preempting RT task on the same - * cache hot CPU will force the running RT task to - * a cold CPU. So we waste all the cache for the lower - * RT task in hopes of saving some of a RT task - * that is just being woken and probably will have - * cold cache anyway. + * We want to avoid overloading runqueues. If the woken + * task is a higher priority, then it will stay on this CPU + * and the lower prio task should be moved to another CPU. + * Even though this will probably make the lower prio task + * lose its cache, we do not want to bounce a higher task + * around just because it gave up its CPU, perhaps for a + * lock? + * + * For equal prio tasks, we just let the scheduler sort it out. */ if (unlikely(rt_task(rq->curr)) && + rq->curr->prio < p->prio && (p->rt.nr_cpus_allowed > 1)) { int cpu = find_lowest_rq(p); @@ -1491,6 +1491,8 @@ static void task_woken_rt(struct rq *rq, struct task_struct *p) if (!task_running(rq, p) && !test_tsk_need_resched(rq->curr) && has_pushable_tasks(rq) && + rt_task(rq->curr) && + rq->curr->prio < p->prio && p->rt.nr_cpus_allowed > 1) push_rt_tasks(rq); } -- cgit v1.2.3 From 54b79ba6355064fdbcea6bf96e28c148efc1c924 Mon Sep 17 00:00:00 2001 From: stable-bot for Steven Rostedt Date: Thu, 10 Feb 2011 10:21:08 +0100 Subject: sched: Give CPU bound RT tasks preference From:: Steven Rostedt Commit: b3bc211cfe7d5fe94b310480d78e00bea96fbf2a upstream If a high priority task is waking up on a CPU that is running a lower priority task that is bound to a CPU, see if we can move the high RT task to another CPU first. Note, if all other CPUs are running higher priority tasks than the CPU bounded current task, then it will be preempted regardless. Signed-off-by: Steven Rostedt Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen Cc: Gregory Haskins LKML-Reference: <20100921024138.888922071@goodmis.org> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- kernel/sched_rt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 86a2f77977c6..25bd3a3ca0cc 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -971,7 +971,8 @@ select_task_rq_rt(struct rq *rq, struct task_struct *p, int sd_flag, int flags) * For equal prio tasks, we just let the scheduler sort it out. */ if (unlikely(rt_task(rq->curr)) && - rq->curr->prio < p->prio && + (rq->curr->rt.nr_cpus_allowed < 2 || + rq->curr->prio < p->prio) && (p->rt.nr_cpus_allowed > 1)) { int cpu = find_lowest_rq(p); @@ -1491,9 +1492,10 @@ static void task_woken_rt(struct rq *rq, struct task_struct *p) if (!task_running(rq, p) && !test_tsk_need_resched(rq->curr) && has_pushable_tasks(rq) && + p->rt.nr_cpus_allowed > 1 && rt_task(rq->curr) && - rq->curr->prio < p->prio && - p->rt.nr_cpus_allowed > 1) + (rq->curr->rt.nr_cpus_allowed < 2 || + rq->curr->prio < p->prio)) push_rt_tasks(rq); } -- cgit v1.2.3 From 279d138207ac3273bd233f75aba8eb49b2f1bc0f Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 10 Feb 2011 10:22:08 +0100 Subject: sched: suppress RCU lockdep splat in task_fork_fair Commit: b0a0f667a349247bd7f05f806b662a25653822bc upstream > =================================================== > [ INFO: suspicious rcu_dereference_check() usage. ] > --------------------------------------------------- > /home/greearb/git/linux.wireless-testing/kernel/sched.c:618 invoked rcu_dereference_check() without protection! > > other info that might help us debug this: > > rcu_scheduler_active = 1, debug_locks = 1 > 1 lock held by ifup/23517: > #0: (&rq->lock){-.-.-.}, at: [] task_fork_fair+0x3b/0x108 > > stack backtrace: > Pid: 23517, comm: ifup Not tainted 2.6.36-rc6-wl+ #5 > Call Trace: > [] ? printk+0xf/0x16 > [] lockdep_rcu_dereference+0x74/0x7d > [] task_group+0x6d/0x79 > [] set_task_rq+0xe/0x57 > [] task_fork_fair+0x57/0x108 > [] sched_fork+0x82/0xf9 > [] copy_process+0x569/0xe8e > [] do_fork+0x118/0x262 > [] ? do_page_fault+0x16a/0x2cf > [] ? up_read+0x16/0x2a > [] sys_clone+0x1b/0x20 > [] ptregs_clone+0x15/0x30 > [] ? sysenter_do_call+0x12/0x38 Here a newly created task is having its runqueue assigned. The new task is not yet on the tasklist, so cannot go away. This is therefore a false positive, suppress with an RCU read-side critical section. Reported-by: Ben Greear Signed-off-by: Andi Kleen Tested-by: Ben Greear Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- kernel/sched_fair.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index e71d44e5bf55..dc57eb8c129e 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -3547,8 +3547,11 @@ static void task_fork_fair(struct task_struct *p) raw_spin_lock_irqsave(&rq->lock, flags); - if (unlikely(task_cpu(p) != this_cpu)) + if (unlikely(task_cpu(p) != this_cpu)) { + rcu_read_lock(); __set_task_cpu(p, this_cpu); + rcu_read_unlock(); + } update_curr(cfs_rq); -- cgit v1.2.3 From 1f8e01cc3447bb1c18014be7de43e1fef344e0c1 Mon Sep 17 00:00:00 2001 From: Nikhil Rao Date: Thu, 10 Feb 2011 10:23:25 +0100 Subject: sched: Do not consider SCHED_IDLE tasks to be cache hot Commit: ef8002f6848236de5adc613063ebeabddea8a6fb upstream This patch adds a check in task_hot to return if the task has SCHED_IDLE policy. SCHED_IDLE tasks have very low weight, and when run with regular workloads, are typically scheduled many milliseconds apart. There is no need to consider these tasks hot for load balancing. Signed-off-by: Nikhil Rao Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <1287173550-30365-2-git-send-email-ncrao@google.com> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/sched.c b/kernel/sched.c index 1747071e26f1..5ea39ade3ad6 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1972,6 +1972,9 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd) if (p->sched_class != &fair_sched_class) return 0; + if (unlikely(p->policy == SCHED_IDLE)) + return 0; + /* * Buddy candidates are cache hot: */ -- cgit v1.2.3 From 56cb45ba8f738f979621b4f91b21908b4226bbe6 Mon Sep 17 00:00:00 2001 From: Nikhil Rao Date: Thu, 10 Feb 2011 10:23:25 +0100 Subject: sched: Set group_imb only a task can be pulled from the busiest cpu Commit: 2582f0eba54066b5e98ff2b27ef0cfa833b59f54 upstream When cycling through sched groups to determine the busiest group, set group_imb only if the busiest cpu has more than 1 runnable task. This patch fixes the case where two cpus in a group have one runnable task each, but there is a large weight differential between these two tasks. The load balancer is unable to migrate any task from this group, and hence do not consider this group to be imbalanced. Signed-off-by: Nikhil Rao Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <1286996978-7007-3-git-send-email-ncrao@google.com> [ small code readability edits ] Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- kernel/sched_fair.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index dc57eb8c129e..db9fbc36d07b 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -2352,7 +2352,7 @@ static inline void update_sg_lb_stats(struct sched_domain *sd, int local_group, const struct cpumask *cpus, int *balance, struct sg_lb_stats *sgs) { - unsigned long load, max_cpu_load, min_cpu_load; + unsigned long load, max_cpu_load, min_cpu_load, max_nr_running; int i; unsigned int balance_cpu = -1, first_idle_cpu = 0; unsigned long avg_load_per_task = 0; @@ -2363,6 +2363,7 @@ static inline void update_sg_lb_stats(struct sched_domain *sd, /* Tally up the load of all CPUs in the group */ max_cpu_load = 0; min_cpu_load = ~0UL; + max_nr_running = 0; for_each_cpu_and(i, sched_group_cpus(group), cpus) { struct rq *rq = cpu_rq(i); @@ -2380,8 +2381,10 @@ static inline void update_sg_lb_stats(struct sched_domain *sd, load = target_load(i, load_idx); } else { load = source_load(i, load_idx); - if (load > max_cpu_load) + if (load > max_cpu_load) { max_cpu_load = load; + max_nr_running = rq->nr_running; + } if (min_cpu_load > load) min_cpu_load = load; } @@ -2421,11 +2424,10 @@ static inline void update_sg_lb_stats(struct sched_domain *sd, if (sgs->sum_nr_running) avg_load_per_task = sgs->sum_weighted_load / sgs->sum_nr_running; - if ((max_cpu_load - min_cpu_load) > 2*avg_load_per_task) + if ((max_cpu_load - min_cpu_load) > 2*avg_load_per_task && max_nr_running > 1) sgs->group_imb = 1; - sgs->group_capacity = - DIV_ROUND_CLOSEST(group->cpu_power, SCHED_LOAD_SCALE); + sgs->group_capacity = DIV_ROUND_CLOSEST(group->cpu_power, SCHED_LOAD_SCALE); } /** -- cgit v1.2.3 From ea529386cb43daded114d0b8804060e32b2c3e9d Mon Sep 17 00:00:00 2001 From: Nikhil Rao Date: Thu, 10 Feb 2011 10:23:25 +0100 Subject: sched: Force balancing on newidle balance if local group has capacity Commit: fab476228ba37907ad75216d0fd9732ada9c119e upstream This patch forces a load balance on a newly idle cpu when the local group has extra capacity and the busiest group does not have any. It improves system utilization when balancing tasks with a large weight differential. Under certain situations, such as a niced down task (i.e. nice = -15) in the presence of nr_cpus NICE0 tasks, the niced task lands on a sched group and kicks away other tasks because of its large weight. This leads to sub-optimal utilization of the machine. Even though the sched group has capacity, it does not pull tasks because sds.this_load >> sds.max_load, and f_b_g() returns NULL. With this patch, if the local group has extra capacity, we shortcut the checks in f_b_g() and try to pull a task over. A sched group has extra capacity if the group capacity is greater than the number of running tasks in that group. Thanks to Mike Galbraith for discussions leading to this patch and for the insight to reuse SD_NEWIDLE_BALANCE. Signed-off-by: Nikhil Rao Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <1287173550-30365-4-git-send-email-ncrao@google.com> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- kernel/sched_fair.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index db9fbc36d07b..05ef09565332 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1765,6 +1765,10 @@ static void pull_task(struct rq *src_rq, struct task_struct *p, set_task_cpu(p, this_cpu); activate_task(this_rq, p, 0); check_preempt_curr(this_rq, p, 0); + + /* re-arm NEWIDLE balancing when moving tasks */ + src_rq->avg_idle = this_rq->avg_idle = 2*sysctl_sched_migration_cost; + this_rq->idle_stamp = 0; } /* @@ -2031,12 +2035,14 @@ struct sd_lb_stats { unsigned long this_load; unsigned long this_load_per_task; unsigned long this_nr_running; + unsigned long this_has_capacity; /* Statistics of the busiest group */ unsigned long max_load; unsigned long busiest_load_per_task; unsigned long busiest_nr_running; unsigned long busiest_group_capacity; + unsigned long busiest_has_capacity; int group_imb; /* Is there imbalance in this sd */ #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) @@ -2059,6 +2065,7 @@ struct sg_lb_stats { unsigned long sum_weighted_load; /* Weighted load of group's tasks */ unsigned long group_capacity; int group_imb; /* Is there an imbalance in the group ? */ + int group_has_capacity; /* Is there extra capacity in the group? */ }; /** @@ -2428,6 +2435,9 @@ static inline void update_sg_lb_stats(struct sched_domain *sd, sgs->group_imb = 1; sgs->group_capacity = DIV_ROUND_CLOSEST(group->cpu_power, SCHED_LOAD_SCALE); + + if (sgs->group_capacity > sgs->sum_nr_running) + sgs->group_has_capacity = 1; } /** @@ -2484,6 +2494,7 @@ static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu, sds->this = group; sds->this_nr_running = sgs.sum_nr_running; sds->this_load_per_task = sgs.sum_weighted_load; + sds->this_has_capacity = sgs.group_has_capacity; } else if (sgs.avg_load > sds->max_load && (sgs.sum_nr_running > sgs.group_capacity || sgs.group_imb)) { @@ -2492,6 +2503,7 @@ static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu, sds->busiest_nr_running = sgs.sum_nr_running; sds->busiest_group_capacity = sgs.group_capacity; sds->busiest_load_per_task = sgs.sum_weighted_load; + sds->busiest_has_capacity = sgs.group_has_capacity; sds->group_imb = sgs.group_imb; } @@ -2637,6 +2649,7 @@ static inline void calculate_imbalance(struct sd_lb_stats *sds, int this_cpu, return fix_small_imbalance(sds, this_cpu, imbalance); } + /******* find_busiest_group() helpers end here *********************/ /** @@ -2688,6 +2701,11 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, * 4) This group is more busy than the avg busieness at this * sched_domain. * 5) The imbalance is within the specified limit. + * + * Note: when doing newidle balance, if the local group has excess + * capacity (i.e. nr_running < group_capacity) and the busiest group + * does not have any capacity, we force a load balance to pull tasks + * to the local group. In this case, we skip past checks 3, 4 and 5. */ if (!(*balance)) goto ret; @@ -2695,6 +2713,11 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, if (!sds.busiest || sds.busiest_nr_running == 0) goto out_balanced; + /* SD_BALANCE_NEWIDLE trumps SMP nice when underutilized */ + if (idle == CPU_NEWLY_IDLE && sds.this_has_capacity && + !sds.busiest_has_capacity) + goto force_balance; + if (sds.this_load >= sds.max_load) goto out_balanced; @@ -2706,6 +2729,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, if (100 * sds.max_load <= sd->imbalance_pct * sds.this_load) goto out_balanced; +force_balance: /* Looks like there is an imbalance. Compute it */ calculate_imbalance(&sds, this_cpu, imbalance); return sds.busiest; @@ -3024,10 +3048,8 @@ static void idle_balance(int this_cpu, struct rq *this_rq) interval = msecs_to_jiffies(sd->balance_interval); if (time_after(next_balance, sd->last_balance + interval)) next_balance = sd->last_balance + interval; - if (pulled_task) { - this_rq->idle_stamp = 0; + if (pulled_task) break; - } } raw_spin_lock(&this_rq->lock); -- cgit v1.2.3 From 3af2f86eee3c8892a9feb5a7866c2cd94e7678b4 Mon Sep 17 00:00:00 2001 From: Nikhil Rao Date: Thu, 10 Feb 2011 10:23:26 +0100 Subject: sched: Drop group_capacity to 1 only if local group has extra capacity Commit: 75dd321d79d495a0ee579e6249ebc38ddbb2667f upstream When SD_PREFER_SIBLING is set on a sched domain, drop group_capacity to 1 only if the local group has extra capacity. The extra check prevents the case where you always pull from the heaviest group when it is already under-utilized (possible with a large weight task outweighs the tasks on the system). For example, consider a 16-cpu quad-core quad-socket machine with MC and NUMA scheduling domains. Let's say we spawn 15 nice0 tasks and one nice-15 task, and each task is running on one core. In this case, we observe the following events when balancing at the NUMA domain: - find_busiest_group() will always pick the sched group containing the niced task to be the busiest group. - find_busiest_queue() will then always pick one of the cpus running the nice0 task (never picks the cpu with the nice -15 task since weighted_cpuload > imbalance). - The load balancer fails to migrate the task since it is the running task and increments sd->nr_balance_failed. - It repeats the above steps a few more times until sd->nr_balance_failed > 5, at which point it kicks off the active load balancer, wakes up the migration thread and kicks the nice 0 task off the cpu. The load balancer doesn't stop until we kick out all nice 0 tasks from the sched group, leaving you with 3 idle cpus and one cpu running the nice -15 task. When balancing at the NUMA domain, we drop sgs.group_capacity to 1 if the child domain (in this case MC) has SD_PREFER_SIBLING set. Subsequent load checks are not relevant because the niced task has a very large weight. In this patch, we add an extra condition to the "if(prefer_sibling)" check in update_sd_lb_stats(). We drop the capacity of a group only if the local group has extra capacity, ie. nr_running < group_capacity. This patch preserves the original intent of the prefer_siblings check (to spread tasks across the system in low utilization scenarios) and fixes the case above. It helps in the following ways: - In low utilization cases (where nr_tasks << nr_cpus), we still drop group_capacity down to 1 if we prefer siblings. - On very busy systems (where nr_tasks >> nr_cpus), sgs.nr_running will most likely be > sgs.group_capacity. - When balancing large weight tasks, if the local group does not have extra capacity, we do not pick the group with the niced task as the busiest group. This prevents failed balances, active migration and the under-utilization described above. Signed-off-by: Nikhil Rao Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <1287173550-30365-5-git-send-email-ncrao@google.com> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- kernel/sched_fair.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 05ef09565332..91508ba76214 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -2484,9 +2484,14 @@ static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu, /* * In case the child domain prefers tasks go to siblings * first, lower the group capacity to one so that we'll try - * and move all the excess tasks away. + * and move all the excess tasks away. We lower the capacity + * of a group only if the local group has the capacity to fit + * these excess tasks, i.e. nr_running < group_capacity. The + * extra check prevents the case where you always pull from the + * heaviest group when it is already under-utilized (possible + * with a large weight task outweighs the tasks on the system). */ - if (prefer_sibling) + if (prefer_sibling && !local_group && sds->this_has_capacity) sgs.group_capacity = min(sgs.group_capacity, 1UL); if (local_group) { -- cgit v1.2.3 From 4032f13ae3acede13531d4cc882aa55f3509c4a9 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Thu, 10 Feb 2011 10:23:26 +0100 Subject: sched: Fix softirq time accounting Commit: 75e1056f5c57050415b64cb761a3acc35d91f013 upstream Peter Zijlstra found a bug in the way softirq time is accounted in VIRT_CPU_ACCOUNTING on this thread: http://lkml.indiana.edu/hypermail//linux/kernel/1009.2/01366.html The problem is, softirq processing uses local_bh_disable internally. There is no way, later in the flow, to differentiate between whether softirq is being processed or is it just that bh has been disabled. So, a hardirq when bh is disabled results in time being wrongly accounted as softirq. Looking at the code a bit more, the problem exists in !VIRT_CPU_ACCOUNTING as well. As account_system_time() in normal tick based accouting also uses softirq_count, which will be set even when not in softirq with bh disabled. Peter also suggested solution of using 2*SOFTIRQ_OFFSET as irq count for local_bh_{disable,enable} and using just SOFTIRQ_OFFSET while softirq processing. The patch below does that and adds API in_serving_softirq() which returns whether we are currently processing softirq or not. Also changes one of the usages of softirq_count in net/sched/cls_cgroup.c to in_serving_softirq. Looks like many usages of in_softirq really want in_serving_softirq. Those changes can be made individually on a case by case basis. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <1286237003-12406-2-git-send-email-venki@google.com> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- include/linux/hardirq.h | 5 +++++ include/linux/sched.h | 6 +++--- kernel/sched.c | 2 +- kernel/softirq.c | 51 ++++++++++++++++++++++++++++++++----------------- net/sched/cls_cgroup.c | 2 +- 5 files changed, 44 insertions(+), 22 deletions(-) diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index d5b387669dab..e37a77cbd588 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h @@ -64,6 +64,8 @@ #define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT) #define NMI_OFFSET (1UL << NMI_SHIFT) +#define SOFTIRQ_DISABLE_OFFSET (2 * SOFTIRQ_OFFSET) + #ifndef PREEMPT_ACTIVE #define PREEMPT_ACTIVE_BITS 1 #define PREEMPT_ACTIVE_SHIFT (NMI_SHIFT + NMI_BITS) @@ -82,10 +84,13 @@ /* * Are we doing bottom half or hardware interrupt processing? * Are we in a softirq context? Interrupt context? + * in_softirq - Are we currently processing softirq or have bh disabled? + * in_serving_softirq - Are we currently processing softirq? */ #define in_irq() (hardirq_count()) #define in_softirq() (softirq_count()) #define in_interrupt() (irq_count()) +#define in_serving_softirq() (softirq_count() & SOFTIRQ_OFFSET) /* * Are we in NMI context? diff --git a/include/linux/sched.h b/include/linux/sched.h index 1272de4e7b3f..c5baae6b1eee 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2363,9 +2363,9 @@ extern int __cond_resched_lock(spinlock_t *lock); extern int __cond_resched_softirq(void); -#define cond_resched_softirq() ({ \ - __might_sleep(__FILE__, __LINE__, SOFTIRQ_OFFSET); \ - __cond_resched_softirq(); \ +#define cond_resched_softirq() ({ \ + __might_sleep(__FILE__, __LINE__, SOFTIRQ_DISABLE_OFFSET); \ + __cond_resched_softirq(); \ }) /* diff --git a/kernel/sched.c b/kernel/sched.c index 5ea39ade3ad6..0e1e64a7ef6f 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3363,7 +3363,7 @@ void account_system_time(struct task_struct *p, int hardirq_offset, tmp = cputime_to_cputime64(cputime); if (hardirq_count() - hardirq_offset) cpustat->irq = cputime64_add(cpustat->irq, tmp); - else if (softirq_count()) + else if (in_serving_softirq()) cpustat->softirq = cputime64_add(cpustat->softirq, tmp); else cpustat->system = cputime64_add(cpustat->system, tmp); diff --git a/kernel/softirq.c b/kernel/softirq.c index 07b4f1b1a73a..988dfbe6bbe8 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -76,12 +76,22 @@ void wakeup_softirqd(void) wake_up_process(tsk); } +/* + * preempt_count and SOFTIRQ_OFFSET usage: + * - preempt_count is changed by SOFTIRQ_OFFSET on entering or leaving + * softirq processing. + * - preempt_count is changed by SOFTIRQ_DISABLE_OFFSET (= 2 * SOFTIRQ_OFFSET) + * on local_bh_disable or local_bh_enable. + * This lets us distinguish between whether we are currently processing + * softirq and whether we just have bh disabled. + */ + /* * This one is for softirq.c-internal use, * where hardirqs are disabled legitimately: */ #ifdef CONFIG_TRACE_IRQFLAGS -static void __local_bh_disable(unsigned long ip) +static void __local_bh_disable(unsigned long ip, unsigned int cnt) { unsigned long flags; @@ -95,32 +105,43 @@ static void __local_bh_disable(unsigned long ip) * We must manually increment preempt_count here and manually * call the trace_preempt_off later. */ - preempt_count() += SOFTIRQ_OFFSET; + preempt_count() += cnt; /* * Were softirqs turned off above: */ - if (softirq_count() == SOFTIRQ_OFFSET) + if (softirq_count() == cnt) trace_softirqs_off(ip); raw_local_irq_restore(flags); - if (preempt_count() == SOFTIRQ_OFFSET) + if (preempt_count() == cnt) trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); } #else /* !CONFIG_TRACE_IRQFLAGS */ -static inline void __local_bh_disable(unsigned long ip) +static inline void __local_bh_disable(unsigned long ip, unsigned int cnt) { - add_preempt_count(SOFTIRQ_OFFSET); + add_preempt_count(cnt); barrier(); } #endif /* CONFIG_TRACE_IRQFLAGS */ void local_bh_disable(void) { - __local_bh_disable((unsigned long)__builtin_return_address(0)); + __local_bh_disable((unsigned long)__builtin_return_address(0), + SOFTIRQ_DISABLE_OFFSET); } EXPORT_SYMBOL(local_bh_disable); +static void __local_bh_enable(unsigned int cnt) +{ + WARN_ON_ONCE(in_irq()); + WARN_ON_ONCE(!irqs_disabled()); + + if (softirq_count() == cnt) + trace_softirqs_on((unsigned long)__builtin_return_address(0)); + sub_preempt_count(cnt); +} + /* * Special-case - softirqs can safely be enabled in * cond_resched_softirq(), or by __do_softirq(), @@ -128,12 +149,7 @@ EXPORT_SYMBOL(local_bh_disable); */ void _local_bh_enable(void) { - WARN_ON_ONCE(in_irq()); - WARN_ON_ONCE(!irqs_disabled()); - - if (softirq_count() == SOFTIRQ_OFFSET) - trace_softirqs_on((unsigned long)__builtin_return_address(0)); - sub_preempt_count(SOFTIRQ_OFFSET); + __local_bh_enable(SOFTIRQ_DISABLE_OFFSET); } EXPORT_SYMBOL(_local_bh_enable); @@ -147,13 +163,13 @@ static inline void _local_bh_enable_ip(unsigned long ip) /* * Are softirqs going to be turned on now: */ - if (softirq_count() == SOFTIRQ_OFFSET) + if (softirq_count() == SOFTIRQ_DISABLE_OFFSET) trace_softirqs_on(ip); /* * Keep preemption disabled until we are done with * softirq processing: */ - sub_preempt_count(SOFTIRQ_OFFSET - 1); + sub_preempt_count(SOFTIRQ_DISABLE_OFFSET - 1); if (unlikely(!in_interrupt() && local_softirq_pending())) do_softirq(); @@ -198,7 +214,8 @@ asmlinkage void __do_softirq(void) pending = local_softirq_pending(); account_system_vtime(current); - __local_bh_disable((unsigned long)__builtin_return_address(0)); + __local_bh_disable((unsigned long)__builtin_return_address(0), + SOFTIRQ_OFFSET); lockdep_softirq_enter(); cpu = smp_processor_id(); @@ -245,7 +262,7 @@ restart: lockdep_softirq_exit(); account_system_vtime(current); - _local_bh_enable(); + __local_bh_enable(SOFTIRQ_OFFSET); } #ifndef __ARCH_HAS_DO_SOFTIRQ diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c index 08be223fb3dc..d49c40fb7e09 100644 --- a/net/sched/cls_cgroup.c +++ b/net/sched/cls_cgroup.c @@ -121,7 +121,7 @@ static int cls_cgroup_classify(struct sk_buff *skb, struct tcf_proto *tp, * calls by looking at the number of nested bh disable calls because * softirqs always disables bh. */ - if (softirq_count() != SOFTIRQ_OFFSET) { + if (in_serving_softirq()) { /* If there is an sk_classid we'll use that. */ if (!skb->sk) return -1; -- cgit v1.2.3 From bc03fafaa1d9cd28c4981cf9eeffb60841deeb76 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Thu, 10 Feb 2011 10:23:26 +0100 Subject: sched: Consolidate account_system_vtime extern declaration Commit: e1e10a265d28273ab8c70be19d43dcbdeead6c5a upstream Just a minor cleanup patch that makes things easier to the following patches. No functionality change in this patch. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <1286237003-12406-3-git-send-email-venki@google.com> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- arch/ia64/include/asm/system.h | 4 ---- arch/powerpc/include/asm/system.h | 4 ---- arch/s390/include/asm/system.h | 1 - include/linux/hardirq.h | 2 ++ 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/arch/ia64/include/asm/system.h b/arch/ia64/include/asm/system.h index 9f342a574ce8..dd028f2b13b3 100644 --- a/arch/ia64/include/asm/system.h +++ b/arch/ia64/include/asm/system.h @@ -272,10 +272,6 @@ void cpu_idle_wait(void); void default_idle(void); -#ifdef CONFIG_VIRT_CPU_ACCOUNTING -extern void account_system_vtime(struct task_struct *); -#endif - #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ diff --git a/arch/powerpc/include/asm/system.h b/arch/powerpc/include/asm/system.h index a6297c67c3d6..880fb572869b 100644 --- a/arch/powerpc/include/asm/system.h +++ b/arch/powerpc/include/asm/system.h @@ -545,10 +545,6 @@ extern void reloc_got2(unsigned long); #define PTRRELOC(x) ((typeof(x)) add_reloc_offset((unsigned long)(x))) -#ifdef CONFIG_VIRT_CPU_ACCOUNTING -extern void account_system_vtime(struct task_struct *); -#endif - extern struct dentry *powerpc_debugfs_root; #endif /* __KERNEL__ */ diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h index cef66210c846..38ddd8a9a9e8 100644 --- a/arch/s390/include/asm/system.h +++ b/arch/s390/include/asm/system.h @@ -97,7 +97,6 @@ static inline void restore_access_regs(unsigned int *acrs) extern void account_vtime(struct task_struct *, struct task_struct *); extern void account_tick_vtime(struct task_struct *); -extern void account_system_vtime(struct task_struct *); #ifdef CONFIG_PFAULT extern void pfault_irq_init(void); diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index e37a77cbd588..41367c5c3c68 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h @@ -141,6 +141,8 @@ struct task_struct; static inline void account_system_vtime(struct task_struct *tsk) { } +#else +extern void account_system_vtime(struct task_struct *tsk); #endif #if defined(CONFIG_NO_HZ) -- cgit v1.2.3 From aa42a9b327e862d49d3695fe88b6833d18ecd285 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Thu, 10 Feb 2011 10:23:26 +0100 Subject: sched: Remove unused PF_ALIGNWARN flag Commit: 637bbdc5b83615ef9f45f50399d1c7f27473c713 upstream PF_ALIGNWARN is not implemented and it is for 486 as the comment. It is not likely someone will implement this flag feature. So here remove this flag and leave the valuable 0x00000001 for future use. Signed-off-by: Dave Young Signed-off-by: Andi Kleen Cc: Peter Zijlstra Cc: Linus Torvalds LKML-Reference: <20100913121903.GB22238@darkstar> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- include/linux/sched.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index c5baae6b1eee..251f1ca9d8b8 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1685,8 +1685,6 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t * /* * Per process flags */ -#define PF_ALIGNWARN 0x00000001 /* Print alignment warning msgs */ - /* Not implemented yet, only for 486*/ #define PF_STARTING 0x00000002 /* being created */ #define PF_EXITING 0x00000004 /* getting shut down */ #define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */ -- cgit v1.2.3 From 70501ead1f5f8760d9ec1c3fd7f69cfe62c5f35e Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Thu, 10 Feb 2011 10:23:27 +0100 Subject: sched: Add a PF flag for ksoftirqd identification Commit: 6cdd5199daf0cb7b0fcc8dca941af08492612887 upstream To account softirq time cleanly in scheduler, we need to identify whether softirq is invoked in ksoftirqd context or softirq at hardirq tail context. Add PF_KSOFTIRQD for that purpose. As all PF flag bits are currently taken, create space by moving one of the infrequently used bits (PF_THREAD_BOUND) down in task_struct to be along with some other state fields. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <1286237003-12406-4-git-send-email-venki@google.com> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- include/linux/sched.h | 1 + kernel/softirq.c | 1 + 2 files changed, 2 insertions(+) diff --git a/include/linux/sched.h b/include/linux/sched.h index 251f1ca9d8b8..0a8beefb41cd 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1685,6 +1685,7 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t * /* * Per process flags */ +#define PF_KSOFTIRQD 0x00000001 /* I am ksoftirqd */ #define PF_STARTING 0x00000002 /* being created */ #define PF_EXITING 0x00000004 /* getting shut down */ #define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */ diff --git a/kernel/softirq.c b/kernel/softirq.c index 988dfbe6bbe8..267f7b763ebb 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -713,6 +713,7 @@ static int run_ksoftirqd(void * __bind_cpu) { set_current_state(TASK_INTERRUPTIBLE); + current->flags |= PF_KSOFTIRQD; while (!kthread_should_stop()) { preempt_disable(); if (!local_softirq_pending()) { -- cgit v1.2.3 From 445352de175186a234c6ce1b8e000619ce1d2d1c Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Thu, 10 Feb 2011 10:23:27 +0100 Subject: sched: Add IRQ_TIME_ACCOUNTING, finer accounting of irq time Commit: b52bfee445d315549d41eacf2fa7c156e7d153d5 upstream s390/powerpc/ia64 have support for CONFIG_VIRT_CPU_ACCOUNTING which does the fine granularity accounting of user, system, hardirq, softirq times. Adding that option on archs like x86 will be challenging however, given the state of TSC reliability on various platforms and also the overhead it will add in syscall entry exit. Instead, add a lighter variant that only does finer accounting of hardirq and softirq times, providing precise irq times (instead of timer tick based samples). This accounting is added with a new config option CONFIG_IRQ_TIME_ACCOUNTING so that there won't be any overhead for users not interested in paying the perf penalty. This accounting is based on sched_clock, with the code being generic. So, other archs may find it useful as well. This patch just adds the core logic and does not enable this logic yet. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <1286237003-12406-5-git-send-email-venki@google.com> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- include/linux/hardirq.h | 2 +- include/linux/sched.h | 13 +++++++++++++ kernel/sched.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index 41367c5c3c68..ff43e9268449 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h @@ -137,7 +137,7 @@ extern void synchronize_irq(unsigned int irq); struct task_struct; -#ifndef CONFIG_VIRT_CPU_ACCOUNTING +#if !defined(CONFIG_VIRT_CPU_ACCOUNTING) && !defined(CONFIG_IRQ_TIME_ACCOUNTING) static inline void account_system_vtime(struct task_struct *tsk) { } diff --git a/include/linux/sched.h b/include/linux/sched.h index 0a8beefb41cd..f359bea0983e 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1823,6 +1823,19 @@ extern void sched_clock_idle_wakeup_event(u64 delta_ns); */ extern unsigned long long cpu_clock(int cpu); +#ifdef CONFIG_IRQ_TIME_ACCOUNTING +/* + * An i/f to runtime opt-in for irq time accounting based off of sched_clock. + * The reason for this explicit opt-in is not to have perf penalty with + * slow sched_clocks. + */ +extern void enable_sched_clock_irqtime(void); +extern void disable_sched_clock_irqtime(void); +#else +static inline void enable_sched_clock_irqtime(void) {} +static inline void disable_sched_clock_irqtime(void) {} +#endif + extern unsigned long long task_sched_runtime(struct task_struct *task); extern unsigned long long thread_group_sched_runtime(struct task_struct *task); diff --git a/kernel/sched.c b/kernel/sched.c index 0e1e64a7ef6f..8efa15c99f55 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1819,6 +1819,55 @@ static const struct sched_class rt_sched_class; #define for_each_class(class) \ for (class = sched_class_highest; class; class = class->next) +#ifdef CONFIG_IRQ_TIME_ACCOUNTING + +static DEFINE_PER_CPU(u64, cpu_hardirq_time); +static DEFINE_PER_CPU(u64, cpu_softirq_time); + +static DEFINE_PER_CPU(u64, irq_start_time); +static int sched_clock_irqtime; + +void enable_sched_clock_irqtime(void) +{ + sched_clock_irqtime = 1; +} + +void disable_sched_clock_irqtime(void) +{ + sched_clock_irqtime = 0; +} + +void account_system_vtime(struct task_struct *curr) +{ + unsigned long flags; + int cpu; + u64 now, delta; + + if (!sched_clock_irqtime) + return; + + local_irq_save(flags); + + now = sched_clock(); + cpu = smp_processor_id(); + delta = now - per_cpu(irq_start_time, cpu); + per_cpu(irq_start_time, cpu) = now; + /* + * We do not account for softirq time from ksoftirqd here. + * We want to continue accounting softirq time to ksoftirqd thread + * in that case, so as not to confuse scheduler with a special task + * that do not consume any time, but still wants to run. + */ + if (hardirq_count()) + per_cpu(cpu_hardirq_time, cpu) += delta; + else if (in_serving_softirq() && !(curr->flags & PF_KSOFTIRQD)) + per_cpu(cpu_softirq_time, cpu) += delta; + + local_irq_restore(flags); +} + +#endif + #include "sched_stats.h" static void inc_nr_running(struct rq *rq) -- cgit v1.2.3 From 06dd801446a3e212dc0a2eb6bb03d9ec7438bca1 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Thu, 10 Feb 2011 10:23:27 +0100 Subject: x86: Add IRQ_TIME_ACCOUNTING Commit: e82b8e4ea4f3dffe6e7939f90e78da675fcc450e upstream This patch adds IRQ_TIME_ACCOUNTING option on x86 and runtime enables it when TSC is enabled. This change just enables fine grained irq time accounting, isn't used yet. Following patches use it for different purposes. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <1286237003-12406-6-git-send-email-venki@google.com> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 4 ++++ arch/x86/Kconfig | 11 +++++++++++ arch/x86/kernel/tsc.c | 8 ++++++++ 3 files changed, 23 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index c74ff6f980dc..713c58944da6 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -2672,6 +2672,10 @@ and is between 256 and 4096 characters. It is defined in the file disables clocksource verification at runtime. Used to enable high-resolution timer mode on older hardware, and in virtualized environment. + [x86] noirqtime: Do not use TSC to do irq accounting. + Used to run time disable IRQ_TIME_ACCOUNTING on any + platforms where RDTSC is slow and this accounting + can add overhead. turbografx.map[2|3]= [HW,JOY] TurboGraFX parallel port interface diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index f942bb713a3d..d2b82109a3fa 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -797,6 +797,17 @@ config SCHED_MC making when dealing with multi-core CPU chips at a cost of slightly increased overhead in some places. If unsure say N here. +config IRQ_TIME_ACCOUNTING + bool "Fine granularity task level IRQ time accounting" + default n + ---help--- + Select this option to enable fine granularity task irq time + accounting. This is done by reading a timestamp on each + transitions between softirq and hardirq state, so there can be a + small performance impact. + + If in doubt, say N here. + source "kernel/Kconfig.preempt" config X86_UP_APIC diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 4094ae0fac3c..97cdbe8b732c 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -104,10 +104,14 @@ int __init notsc_setup(char *str) __setup("notsc", notsc_setup); +static int no_sched_irq_time; + static int __init tsc_setup(char *str) { if (!strcmp(str, "reliable")) tsc_clocksource_reliable = 1; + if (!strncmp(str, "noirqtime", 9)) + no_sched_irq_time = 1; return 1; } @@ -802,6 +806,7 @@ void mark_tsc_unstable(char *reason) if (!tsc_unstable) { tsc_unstable = 1; sched_clock_stable = 0; + disable_sched_clock_irqtime(); printk(KERN_INFO "Marking TSC unstable due to %s\n", reason); /* Change only the rating, when not registered */ if (clocksource_tsc.mult) @@ -990,6 +995,9 @@ void __init tsc_init(void) /* now allow native_sched_clock() to use rdtsc */ tsc_disabled = 0; + if (!no_sched_irq_time) + enable_sched_clock_irqtime(); + lpj = ((u64)tsc_khz * 1000); do_div(lpj, HZ); lpj_fine = lpj; -- cgit v1.2.3 From a3fe22ee824895aafdc1b788e19c081a2e6dd9da Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Thu, 10 Feb 2011 10:23:27 +0100 Subject: sched: Do not account irq time to current task Commit: 305e6835e05513406fa12820e40e4a8ecb63743c upstream Scheduler accounts both softirq and interrupt processing times to the currently running task. This means, if the interrupt processing was for some other task in the system, then the current task ends up being penalized as it gets shorter runtime than otherwise. Change sched task accounting to acoount only actual task time from currently running task. Now update_curr(), modifies the delta_exec to depend on rq->clock_task. Note that this change only handles CONFIG_IRQ_TIME_ACCOUNTING case. We can extend this to CONFIG_VIRT_CPU_ACCOUNTING with minimal effort. But, thats for later. This change will impact scheduling behavior in interrupt heavy conditions. Tested on a 4-way system with eth0 handled by CPU 2 and a network heavy task (nc) running on CPU 3 (and no RSS/RFS). With that I have CPU 2 spending 75%+ of its time in irq processing. CPU 3 spending around 35% time running nc task. Now, if I run another CPU intensive task on CPU 2, without this change /proc//schedstat shows 100% of time accounted to this task. With this change, it rightly shows less than 25% accounted to this task as remaining time is actually spent on irq processing. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <1286237003-12406-7-git-send-email-venki@google.com> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 38 +++++++++++++++++++++++++++++++++++++- kernel/sched_fair.c | 6 +++--- kernel/sched_rt.c | 8 ++++---- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 8efa15c99f55..c8796ca43b6e 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -491,6 +491,7 @@ struct rq { struct mm_struct *prev_mm; u64 clock; + u64 clock_task; atomic_t nr_iowait; @@ -641,10 +642,18 @@ static inline struct task_group *task_group(struct task_struct *p) #endif /* CONFIG_CGROUP_SCHED */ +static u64 irq_time_cpu(int cpu); + inline void update_rq_clock(struct rq *rq) { + int cpu = cpu_of(rq); + u64 irq_time; + if (!rq->skip_clock_update) rq->clock = sched_clock_cpu(cpu_of(rq)); + irq_time = irq_time_cpu(cpu); + if (rq->clock - irq_time > rq->clock_task) + rq->clock_task = rq->clock - irq_time; } /* @@ -1821,6 +1830,18 @@ static const struct sched_class rt_sched_class; #ifdef CONFIG_IRQ_TIME_ACCOUNTING +/* + * There are no locks covering percpu hardirq/softirq time. + * They are only modified in account_system_vtime, on corresponding CPU + * with interrupts disabled. So, writes are safe. + * They are read and saved off onto struct rq in update_rq_clock(). + * This may result in other CPU reading this CPU's irq time and can + * race with irq/account_system_vtime on this CPU. We would either get old + * or new value (or semi updated value on 32 bit) with a side effect of + * accounting a slice of irq time to wrong task when irq is in progress + * while we read rq->clock. That is a worthy compromise in place of having + * locks on each irq in account_system_time. + */ static DEFINE_PER_CPU(u64, cpu_hardirq_time); static DEFINE_PER_CPU(u64, cpu_softirq_time); @@ -1837,6 +1858,14 @@ void disable_sched_clock_irqtime(void) sched_clock_irqtime = 0; } +static u64 irq_time_cpu(int cpu) +{ + if (!sched_clock_irqtime) + return 0; + + return per_cpu(cpu_softirq_time, cpu) + per_cpu(cpu_hardirq_time, cpu); +} + void account_system_vtime(struct task_struct *curr) { unsigned long flags; @@ -1866,6 +1895,13 @@ void account_system_vtime(struct task_struct *curr) local_irq_restore(flags); } +#else + +static u64 irq_time_cpu(int cpu) +{ + return 0; +} + #endif #include "sched_stats.h" @@ -3263,7 +3299,7 @@ static u64 do_task_delta_exec(struct task_struct *p, struct rq *rq) if (task_current(rq, p)) { update_rq_clock(rq); - ns = rq->clock - p->se.exec_start; + ns = rq->clock_task - p->se.exec_start; if ((s64)ns < 0) ns = 0; } diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 91508ba76214..32112033b7bc 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -519,7 +519,7 @@ __update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr, static void update_curr(struct cfs_rq *cfs_rq) { struct sched_entity *curr = cfs_rq->curr; - u64 now = rq_of(cfs_rq)->clock; + u64 now = rq_of(cfs_rq)->clock_task; unsigned long delta_exec; if (unlikely(!curr)) @@ -602,7 +602,7 @@ update_stats_curr_start(struct cfs_rq *cfs_rq, struct sched_entity *se) /* * We are starting a new run period: */ - se->exec_start = rq_of(cfs_rq)->clock; + se->exec_start = rq_of(cfs_rq)->clock_task; } /************************************************** @@ -1803,7 +1803,7 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu, * 2) too many balance attempts have failed. */ - tsk_cache_hot = task_hot(p, rq->clock, sd); + tsk_cache_hot = task_hot(p, rq->clock_task, sd); if (!tsk_cache_hot || sd->nr_balance_failed > sd->cache_nice_tries) { #ifdef CONFIG_SCHEDSTATS diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 25bd3a3ca0cc..a851cc0796b3 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -609,7 +609,7 @@ static void update_curr_rt(struct rq *rq) if (!task_has_rt_policy(curr)) return; - delta_exec = rq->clock - curr->se.exec_start; + delta_exec = rq->clock_task - curr->se.exec_start; if (unlikely((s64)delta_exec < 0)) delta_exec = 0; @@ -618,7 +618,7 @@ static void update_curr_rt(struct rq *rq) curr->se.sum_exec_runtime += delta_exec; account_group_exec_runtime(curr, delta_exec); - curr->se.exec_start = rq->clock; + curr->se.exec_start = rq->clock_task; cpuacct_charge(curr, delta_exec); sched_rt_avg_update(rq, delta_exec); @@ -1075,7 +1075,7 @@ static struct task_struct *_pick_next_task_rt(struct rq *rq) } while (rt_rq); p = rt_task_of(rt_se); - p->se.exec_start = rq->clock; + p->se.exec_start = rq->clock_task; return p; } @@ -1716,7 +1716,7 @@ static void set_curr_task_rt(struct rq *rq) { struct task_struct *p = rq->curr; - p->se.exec_start = rq->clock; + p->se.exec_start = rq->clock_task; /* The running task is never eligible for pushing */ dequeue_pushable_task(rq, p); -- cgit v1.2.3 From fd72c5feeb61857dbcc4fac1c98157925fbb085e Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Thu, 10 Feb 2011 10:23:27 +0100 Subject: sched: Remove irq time from available CPU power Commit: aa483808516ca5cacfa0e5849691f64fec25828e upstream The idea was suggested by Peter Zijlstra here: http://marc.info/?l=linux-kernel&m=127476934517534&w=2 irq time is technically not available to the tasks running on the CPU. This patch removes irq time from CPU power piggybacking on sched_rt_avg_update(). Tested this by keeping CPU X busy with a network intensive task having 75% oa a single CPU irq processing (hard+soft) on a 4-way system. And start seven cycle soakers on the system. Without this change, there will be two tasks on each CPU. With this change, there is a single task on irq busy CPU X and remaining 7 tasks are spread around among other 3 CPUs. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <1286237003-12406-8-git-send-email-venki@google.com> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 18 ++++++++++++++++++ kernel/sched_fair.c | 7 ++++++- kernel/sched_features.h | 5 +++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/kernel/sched.c b/kernel/sched.c index c8796ca43b6e..97a989b6fcff 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -519,6 +519,10 @@ struct rq { u64 avg_idle; #endif +#ifdef CONFIG_IRQ_TIME_ACCOUNTING + u64 prev_irq_time; +#endif + /* calc_load related fields */ unsigned long calc_load_update; long calc_load_active; @@ -643,6 +647,7 @@ static inline struct task_group *task_group(struct task_struct *p) #endif /* CONFIG_CGROUP_SCHED */ static u64 irq_time_cpu(int cpu); +static void sched_irq_time_avg_update(struct rq *rq, u64 irq_time); inline void update_rq_clock(struct rq *rq) { @@ -654,6 +659,8 @@ inline void update_rq_clock(struct rq *rq) irq_time = irq_time_cpu(cpu); if (rq->clock - irq_time > rq->clock_task) rq->clock_task = rq->clock - irq_time; + + sched_irq_time_avg_update(rq, irq_time); } /* @@ -1895,6 +1902,15 @@ void account_system_vtime(struct task_struct *curr) local_irq_restore(flags); } +static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) +{ + if (sched_clock_irqtime && sched_feat(NONIRQ_POWER)) { + u64 delta_irq = curr_irq_time - rq->prev_irq_time; + rq->prev_irq_time = curr_irq_time; + sched_rt_avg_update(rq, delta_irq); + } +} + #else static u64 irq_time_cpu(int cpu) @@ -1902,6 +1918,8 @@ static u64 irq_time_cpu(int cpu) return 0; } +static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) { } + #endif #include "sched_stats.h" diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 32112033b7bc..4a9793e09672 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -2276,8 +2276,13 @@ unsigned long scale_rt_power(int cpu) u64 total, available; total = sched_avg_period() + (rq->clock - rq->age_stamp); - available = total - rq->rt_avg; + if (unlikely(total < rq->rt_avg)) { + /* Ensures that power won't end up being negative */ + available = 0; + } else { + available = total - rq->rt_avg; + } if (unlikely((s64)total < SCHED_LOAD_SCALE)) total = SCHED_LOAD_SCALE; diff --git a/kernel/sched_features.h b/kernel/sched_features.h index 83c66e8ad3ee..185f920ec1a2 100644 --- a/kernel/sched_features.h +++ b/kernel/sched_features.h @@ -61,3 +61,8 @@ SCHED_FEAT(ASYM_EFF_LOAD, 1) * release the lock. Decreases scheduling overhead. */ SCHED_FEAT(OWNER_SPIN, 1) + +/* + * Decrement CPU power based on irq activity + */ +SCHED_FEAT(NONIRQ_POWER, 1) -- cgit v1.2.3 From 70f43fbf43440db130a7e3daeb276e29ed9a8f80 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Thu, 10 Feb 2011 10:23:28 +0100 Subject: sched: Call tick_check_idle before __irq_enter Commit: d267f87fb8179c6dba03d08b91952e81bc3723c7 upstream When CPU is idle and on first interrupt, irq_enter calls tick_check_idle() to notify interruption from idle. But, there is a problem if this call is done after __irq_enter, as all routines in __irq_enter may find stale time due to yet to be done tick_check_idle. Specifically, trace calls in __irq_enter when they use global clock and also account_system_vtime change in this patch as it wants to use sched_clock_cpu() to do proper irq timing. But, tick_check_idle was moved after __irq_enter intentionally to prevent problem of unneeded ksoftirqd wakeups by the commit ee5f80a: irq: call __irq_enter() before calling the tick_idle_check Impact: avoid spurious ksoftirqd wakeups Moving tick_check_idle() before __irq_enter and wrapping it with local_bh_enable/disable would solve both the problems. Fixed-by: Yong Zhang Signed-off-by: Venkatesh Pallipadi Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <1286237003-12406-9-git-send-email-venki@google.com> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 2 +- kernel/softirq.c | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 97a989b6fcff..c7a66a3ebc7c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1884,8 +1884,8 @@ void account_system_vtime(struct task_struct *curr) local_irq_save(flags); - now = sched_clock(); cpu = smp_processor_id(); + now = sched_clock_cpu(cpu); delta = now - per_cpu(irq_start_time, cpu); per_cpu(irq_start_time, cpu) = now; /* diff --git a/kernel/softirq.c b/kernel/softirq.c index 267f7b763ebb..79ee8f1fc0e7 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -296,10 +296,16 @@ void irq_enter(void) rcu_irq_enter(); if (idle_cpu(cpu) && !in_interrupt()) { - __irq_enter(); + /* + * Prevent raise_softirq from needlessly waking up ksoftirqd + * here, as softirq will be serviced on return from interrupt. + */ + local_bh_disable(); tick_check_idle(cpu); - } else - __irq_enter(); + _local_bh_enable(); + } + + __irq_enter(); } #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED -- cgit v1.2.3 From 0ca4534301c1bd86d00e3ba6beeef045a606e0c5 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 10 Feb 2011 10:23:28 +0100 Subject: sched: Export account_system_vtime() Commit: b7dadc38797584f6203386da1947ed5edf516646 upstream KVM uses it for example: ERROR: "account_system_vtime" [arch/x86/kvm/kvm.ko] undefined! Cc: Venkatesh Pallipadi Cc: Peter Zijlstra LKML-Reference: <1286237003-12406-3-git-send-email-venki@google.com> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/sched.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/sched.c b/kernel/sched.c index c7a66a3ebc7c..4730dff25740 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1901,6 +1901,7 @@ void account_system_vtime(struct task_struct *curr) local_irq_restore(flags); } +EXPORT_SYMBOL_GPL(account_system_vtime); static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) { -- cgit v1.2.3 From 43c34b42474e03b54e11f6f17d87ce1160a83bc0 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 10 Feb 2011 10:23:28 +0100 Subject: sched, cgroup: Fixup broken cgroup movement Commit: b2b5ce022acf5e9f52f7b78c5579994fdde191d4 upstream Dima noticed that we fail to correct the ->vruntime of sleeping tasks when we move them between cgroups. Reported-by: Dima Zavin Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen Tested-by: Mike Galbraith LKML-Reference: <1287150604.29097.1513.camel@twins> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- include/linux/sched.h | 2 +- kernel/sched.c | 8 ++++---- kernel/sched_fair.c | 25 +++++++++++++++++++------ 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index f359bea0983e..0c2e5b5d02cc 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1076,7 +1076,7 @@ struct sched_class { struct task_struct *task); #ifdef CONFIG_FAIR_GROUP_SCHED - void (*moved_group) (struct task_struct *p, int on_rq); + void (*task_move_group) (struct task_struct *p, int on_rq); #endif }; diff --git a/kernel/sched.c b/kernel/sched.c index 4730dff25740..82f64af45d28 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -8332,12 +8332,12 @@ void sched_move_task(struct task_struct *tsk) if (unlikely(running)) tsk->sched_class->put_prev_task(rq, tsk); - set_task_rq(tsk, task_cpu(tsk)); - #ifdef CONFIG_FAIR_GROUP_SCHED - if (tsk->sched_class->moved_group) - tsk->sched_class->moved_group(tsk, on_rq); + if (tsk->sched_class->task_move_group) + tsk->sched_class->task_move_group(tsk, on_rq); + else #endif + set_task_rq(tsk, task_cpu(tsk)); if (unlikely(running)) tsk->sched_class->set_curr_task(rq); diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 4a9793e09672..38ca32a60682 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -3657,13 +3657,26 @@ static void set_curr_task_fair(struct rq *rq) } #ifdef CONFIG_FAIR_GROUP_SCHED -static void moved_group_fair(struct task_struct *p, int on_rq) +static void task_move_group_fair(struct task_struct *p, int on_rq) { - struct cfs_rq *cfs_rq = task_cfs_rq(p); - - update_curr(cfs_rq); + /* + * If the task was not on the rq at the time of this cgroup movement + * it must have been asleep, sleeping tasks keep their ->vruntime + * absolute on their old rq until wakeup (needed for the fair sleeper + * bonus in place_entity()). + * + * If it was on the rq, we've just 'preempted' it, which does convert + * ->vruntime to a relative base. + * + * Make sure both cases convert their relative position when migrating + * to another cgroup's rq. This does somewhat interfere with the + * fair sleeper stuff for the first placement, but who cares. + */ + if (!on_rq) + p->se.vruntime -= cfs_rq_of(&p->se)->min_vruntime; + set_task_rq(p, task_cpu(p)); if (!on_rq) - place_entity(cfs_rq, &p->se, 1); + p->se.vruntime += cfs_rq_of(&p->se)->min_vruntime; } #endif @@ -3715,7 +3728,7 @@ static const struct sched_class fair_sched_class = { .get_rr_interval = get_rr_interval_fair, #ifdef CONFIG_FAIR_GROUP_SCHED - .moved_group = moved_group_fair, + .task_move_group = task_move_group_fair, #endif }; -- cgit v1.2.3 From 118de48b5183dbb3d6281302528ad1a93624854f Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Feb 2011 10:23:28 +0100 Subject: sched: Use group weight, idle cpu metrics to fix imbalances during idle Commit: aae6d3ddd8b90f5b2c8d79a2b914d1706d124193 upstream Currently we consider a sched domain to be well balanced when the imbalance is less than the domain's imablance_pct. As the number of cores and threads are increasing, current values of imbalance_pct (for example 25% for a NUMA domain) are not enough to detect imbalances like: a) On a WSM-EP system (two sockets, each having 6 cores and 12 logical threads), 24 cpu-hogging tasks get scheduled as 13 on one socket and 11 on another socket. Leading to an idle HT cpu. b) On a hypothetial 2 socket NHM-EX system (each socket having 8 cores and 16 logical threads), 16 cpu-hogging tasks can get scheduled as 9 on one socket and 7 on another socket. Leaving one core in a socket idle whereas in another socket we have a core having both its HT siblings busy. While this issue can be fixed by decreasing the domain's imbalance_pct (by making it a function of number of logical cpus in the domain), it can potentially cause more task migrations across sched groups in an overloaded case. Fix this by using imbalance_pct only during newly_idle and busy load balancing. And during idle load balancing, check if there is an imbalance in number of idle cpu's across the busiest and this sched_group or if the busiest group has more tasks than its weight that the idle cpu in this_group can pull. Reported-by: Nikhil Rao Signed-off-by: Suresh Siddha Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <1284760952.2676.11.camel@sbsiddha-MOBL3.sc.intel.com> Signed-off-by: Ingo Molnar Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- include/linux/sched.h | 1 + kernel/sched.c | 2 ++ kernel/sched_fair.c | 34 +++++++++++++++++++++++++++++++--- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 0c2e5b5d02cc..fc531a780124 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -856,6 +856,7 @@ struct sched_group { * single CPU. */ unsigned int cpu_power; + unsigned int group_weight; /* * The CPUs this group covers. diff --git a/kernel/sched.c b/kernel/sched.c index 82f64af45d28..772b2d53cedb 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -6839,6 +6839,8 @@ static void init_sched_groups_power(int cpu, struct sched_domain *sd) if (cpu != group_first_cpu(sd->groups)) return; + sd->groups->group_weight = cpumask_weight(sched_group_cpus(sd->groups)); + child = sd->child; sd->groups->cpu_power = 0; diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 38ca32a60682..09a98114ec32 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -2036,13 +2036,16 @@ struct sd_lb_stats { unsigned long this_load_per_task; unsigned long this_nr_running; unsigned long this_has_capacity; + unsigned int this_idle_cpus; /* Statistics of the busiest group */ + unsigned int busiest_idle_cpus; unsigned long max_load; unsigned long busiest_load_per_task; unsigned long busiest_nr_running; unsigned long busiest_group_capacity; unsigned long busiest_has_capacity; + unsigned int busiest_group_weight; int group_imb; /* Is there imbalance in this sd */ #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) @@ -2064,6 +2067,8 @@ struct sg_lb_stats { unsigned long sum_nr_running; /* Nr tasks running in the group */ unsigned long sum_weighted_load; /* Weighted load of group's tasks */ unsigned long group_capacity; + unsigned long idle_cpus; + unsigned long group_weight; int group_imb; /* Is there an imbalance in the group ? */ int group_has_capacity; /* Is there extra capacity in the group? */ }; @@ -2404,7 +2409,8 @@ static inline void update_sg_lb_stats(struct sched_domain *sd, sgs->group_load += load; sgs->sum_nr_running += rq->nr_running; sgs->sum_weighted_load += weighted_cpuload(i); - + if (idle_cpu(i)) + sgs->idle_cpus++; } /* @@ -2440,6 +2446,7 @@ static inline void update_sg_lb_stats(struct sched_domain *sd, sgs->group_imb = 1; sgs->group_capacity = DIV_ROUND_CLOSEST(group->cpu_power, SCHED_LOAD_SCALE); + sgs->group_weight = group->group_weight; if (sgs->group_capacity > sgs->sum_nr_running) sgs->group_has_capacity = 1; @@ -2505,13 +2512,16 @@ static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu, sds->this_nr_running = sgs.sum_nr_running; sds->this_load_per_task = sgs.sum_weighted_load; sds->this_has_capacity = sgs.group_has_capacity; + sds->this_idle_cpus = sgs.idle_cpus; } else if (sgs.avg_load > sds->max_load && (sgs.sum_nr_running > sgs.group_capacity || sgs.group_imb)) { sds->max_load = sgs.avg_load; sds->busiest = group; sds->busiest_nr_running = sgs.sum_nr_running; + sds->busiest_idle_cpus = sgs.idle_cpus; sds->busiest_group_capacity = sgs.group_capacity; + sds->busiest_group_weight = sgs.group_weight; sds->busiest_load_per_task = sgs.sum_weighted_load; sds->busiest_has_capacity = sgs.group_has_capacity; sds->group_imb = sgs.group_imb; @@ -2736,8 +2746,26 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, if (sds.this_load >= sds.avg_load) goto out_balanced; - if (100 * sds.max_load <= sd->imbalance_pct * sds.this_load) - goto out_balanced; + /* + * In the CPU_NEWLY_IDLE, use imbalance_pct to be conservative. + * And to check for busy balance use !idle_cpu instead of + * CPU_NOT_IDLE. This is because HT siblings will use CPU_NOT_IDLE + * even when they are idle. + */ + if (idle == CPU_NEWLY_IDLE || !idle_cpu(this_cpu)) { + if (100 * sds.max_load <= sd->imbalance_pct * sds.this_load) + goto out_balanced; + } else { + /* + * This cpu is idle. If the busiest group load doesn't + * have more tasks than the number of available cpu's and + * there is no imbalance between this and busiest group + * wrt to idle cpu's, it is balanced. + */ + if ((sds.this_idle_cpus <= sds.busiest_idle_cpus + 1) && + sds.busiest_nr_running <= sds.busiest_group_weight) + goto out_balanced; + } force_balance: /* Looks like there is an imbalance. Compute it */ -- cgit v1.2.3 From cec5d24f1ce6c52f5d2ed93b845e0de40127c88c Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Fri, 11 Feb 2011 07:07:01 +0100 Subject: kernel/user.c: add lock release annotation on free_user() commit 571428be550fbe37160596995e96ad398873fcbd upstream. free_user() releases uidhash_lock but was missing annotation. Add it. This removes following sparse warnings: include/linux/spinlock.h:339:9: warning: context imbalance in 'free_user' - unexpected unlock kernel/user.c:120:6: warning: context imbalance in 'free_uid' - wrong count at exit Signed-off-by: Namhyung Kim Signed-off-by: Andi Kleen Cc: Ingo Molnar Cc: Dhaval Giani Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Mike Galbraith Signed-off-by: Greg Kroah-Hartman --- kernel/user.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/user.c b/kernel/user.c index 8ce395f74d47..5c598ca781df 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -91,6 +91,7 @@ static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent) * upon function exit. */ static void free_user(struct user_struct *up, unsigned long flags) + __releases(&uidhash_lock) { uid_hash_remove(up); spin_unlock_irqrestore(&uidhash_lock, flags); -- cgit v1.2.3 From 6c1ab83daaff423f23209f981936473364bda02f Mon Sep 17 00:00:00 2001 From: Konstantin Khorenko Date: Tue, 1 Feb 2011 17:16:29 +0300 Subject: NFSD: memory corruption due to writing beyond the stat array commit 3aa6e0aa8ab3e64bbfba092c64d42fd1d006b124 upstream. If nfsd fails to find an exported via NFS file in the readahead cache, it should increment corresponding nfsdstats counter (ra_depth[10]), but due to a bug it may instead write to ra_depth[11], corrupting the following field. In a kernel with NFSDv4 compiled in the corruption takes the form of an increment of a counter of the number of NFSv4 operation 0's received; since there is no operation 0, this is harmless. In a kernel with NFSDv4 disabled it corrupts whatever happens to be in the memory beyond nfsdstats. Signed-off-by: Konstantin Khorenko Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfsd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 3c111120b619..40962779c666 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -819,7 +819,7 @@ nfsd_get_raparms(dev_t dev, ino_t ino) if (ra->p_count == 0) frap = rap; } - depth = nfsdstats.ra_size*11/10; + depth = nfsdstats.ra_size; if (!frap) { spin_unlock(&rab->pb_lock); return NULL; -- cgit v1.2.3 From 194ab78ef659f30a0a3d1dc8542a6f0f976b76a5 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 10 Feb 2011 11:52:21 +0530 Subject: mptfusion: mptctl_release is required in mptctl.c commit 84857c8bf83e8aa87afc57d2956ba01f11d82386 upstream. Added missing release callback for file_operations mptctl_fops. Without release callback there will be never freed. It remains on mptctl's eent list even after the file is closed and released. Relavent RHEL bugzilla is 660871 Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/message/fusion/mptctl.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index f06b29193b4e..4dbe5465f728 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -587,6 +587,13 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) return 1; } +static int +mptctl_release(struct inode *inode, struct file *filep) +{ + fasync_helper(-1, filep, 0, &async_queue); + return 0; +} + static int mptctl_fasync(int fd, struct file *filep, int mode) { @@ -2796,6 +2803,7 @@ static const struct file_operations mptctl_fops = { .llseek = no_llseek, .fasync = mptctl_fasync, .unlocked_ioctl = mptctl_ioctl, + .release = mptctl_release, #ifdef CONFIG_COMPAT .compat_ioctl = compat_mpctl_ioctl, #endif -- cgit v1.2.3 From 44c1a1c019045500afd9bb90170ba10d1f5128d7 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 10 Feb 2011 11:53:44 +0530 Subject: mptfusion: Fix Incorrect return value in mptscsih_dev_reset commit bcfe42e98047f1935c5571c8ea77beb2d43ec19d upstream. There's a branch at the end of this function that is supposed to normalize the return value with what the mid-layer expects. In this one case, we get it wrong. Also increase the verbosity of the INFO level printk at the end of mptscsih_abort to include the actual return value and the scmd->serial_number. The reason being success or failure is actually determined by the state of the internal tag list when a TMF is issued, and not the return value of the TMF cmd. The serial_number is also used in this decision, thus it's useful to know for debugging purposes. Reported-by: Peter M. Petrakis Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/message/fusion/mptscsih.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 407cb84822df..ab783a373982 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1848,8 +1848,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) } out: - printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n", - ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), SCpnt); + printk(MYIOC_s_INFO_FMT "task abort: %s (rv=%04x) (sc=%p) (sn=%ld)\n", + ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), retval, + SCpnt, SCpnt->serial_number); return retval; } @@ -1886,7 +1887,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) vdevice = SCpnt->device->hostdata; if (!vdevice || !vdevice->vtarget) { - retval = SUCCESS; + retval = 0; goto out; } -- cgit v1.2.3 From a9ba6fef50d463c4d089c49df24678a6df1d80c9 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Fri, 1 Oct 2010 11:51:47 +0000 Subject: sctp: Fix out-of-bounds reading in sctp_asoc_get_hmac() commit 51e97a12bef19b7e43199fc153cf9bd5f2140362 upstream. The sctp_asoc_get_hmac() function iterates through a peer's hmac_ids array and attempts to ensure that only a supported hmac entry is returned. The current code fails to do this properly - if the last id in the array is out of range (greater than SCTP_AUTH_HMAC_ID_MAX), the id integer remains set after exiting the loop, and the address of an out-of-bounds entry will be returned and subsequently used in the parent function, causing potentially ugly memory corruption. This patch resets the id integer to 0 on encountering an invalid id so that NULL will be returned after finishing the loop if no valid ids are found. Signed-off-by: Dan Rosenberg Acked-by: Vlad Yasevich Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/sctp/auth.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 86366390038a..ddbbf7c81fa1 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -543,16 +543,20 @@ struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc) id = ntohs(hmacs->hmac_ids[i]); /* Check the id is in the supported range */ - if (id > SCTP_AUTH_HMAC_ID_MAX) + if (id > SCTP_AUTH_HMAC_ID_MAX) { + id = 0; continue; + } /* See is we support the id. Supported IDs have name and * length fields set, so that we can allocated and use * them. We can safely just check for name, for without the * name, we can't allocate the TFM. */ - if (!sctp_hmac_list[id].hmac_name) + if (!sctp_hmac_list[id].hmac_name) { + id = 0; continue; + } break; } -- cgit v1.2.3 From ce7f2cfe2de74e8bc53a04c63fd61696b89ffe3e Mon Sep 17 00:00:00 2001 From: dann frazier Date: Thu, 18 Nov 2010 15:03:09 -0700 Subject: ocfs2_connection_find() returns pointer to bad structure commit 226291aa4641fa13cb5dec3bcb3379faa83009e2 upstream. If ocfs2_live_connection_list is empty, ocfs2_connection_find() will return a pointer to the LIST_HEAD, cast as a ocfs2_live_connection. This can cause an oops when ocfs2_control_send_down() dereferences c->oc_conn: Call Trace: [] ocfs2_control_message+0x28c/0x2b0 [ocfs2_stack_user] [] ocfs2_control_write+0x35/0xb0 [ocfs2_stack_user] [] vfs_write+0xb8/0x1a0 [] ? do_page_fault+0x153/0x3b0 [] sys_write+0x51/0x80 [] system_call_fastpath+0x16/0x1b Fix by explicitly returning NULL if no match is found. Signed-off-by: dann frazier Signed-off-by: Joel Becker Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ocfs2/stack_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c index 2dc57bca0688..22db114a4f0a 100644 --- a/fs/ocfs2/stack_user.c +++ b/fs/ocfs2/stack_user.c @@ -191,7 +191,7 @@ static struct ocfs2_live_connection *ocfs2_connection_find(const char *name) return c; } - return c; + return NULL; } /* -- cgit v1.2.3 From ac9a0f1a28f560f2c65ee6e2ae5b750fac9f14cb Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 25 Oct 2010 16:53:46 -0700 Subject: x86/pvclock: Zero last_value on resume commit e7a3481c0246c8e45e79c629efd63b168e91fcda upstream. If the guest domain has been suspend/resumed or migrated, then the system clock backing the pvclock clocksource may revert to a smaller value (ie, can be non-monotonic across the migration/save-restore). Make sure we zero last_value in that case so that the domain continues to see clock updates. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/include/asm/pvclock.h | 1 + arch/x86/kernel/pvclock.c | 5 +++++ arch/x86/xen/time.c | 2 ++ 3 files changed, 8 insertions(+) diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h index cd02f324aa6b..6226870d11cd 100644 --- a/arch/x86/include/asm/pvclock.h +++ b/arch/x86/include/asm/pvclock.h @@ -11,5 +11,6 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src); void pvclock_read_wallclock(struct pvclock_wall_clock *wall, struct pvclock_vcpu_time_info *vcpu, struct timespec *ts); +void pvclock_resume(void); #endif /* _ASM_X86_PVCLOCK_H */ diff --git a/arch/x86/kernel/pvclock.c b/arch/x86/kernel/pvclock.c index 239427ca02af..a4f07c1cfc87 100644 --- a/arch/x86/kernel/pvclock.c +++ b/arch/x86/kernel/pvclock.c @@ -120,6 +120,11 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src) static atomic64_t last_value = ATOMIC64_INIT(0); +void pvclock_resume(void) +{ + atomic64_set(&last_value, 0); +} + cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src) { struct pvclock_shadow_time shadow; diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index a86df42e46ad..41eb583adc8d 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -425,6 +425,8 @@ void xen_timer_resume(void) { int cpu; + pvclock_resume(); + if (xen_clockevent != &xen_vcpuop_clockevent) return; -- cgit v1.2.3 From 515884e98dc4f1c99387000d420394c3bc47c0d7 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 7 Jan 2011 16:41:54 -0300 Subject: av7110: check for negative array offset commit cb26a24ee9706473f31d34cc259f4dcf45cd0644 upstream. info->num comes from the user. It's type int. If the user passes in a negative value that would cause memory corruption. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/media/dvb/ttpci/av7110_ca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c index 4eba35a018e3..c38dd678fd20 100644 --- a/drivers/media/dvb/ttpci/av7110_ca.c +++ b/drivers/media/dvb/ttpci/av7110_ca.c @@ -277,7 +277,7 @@ static int dvb_ca_ioctl(struct file *file, unsigned int cmd, void *parg) { ca_slot_info_t *info=(ca_slot_info_t *)parg; - if (info->num > 1) + if (info->num < 0 || info->num > 1) return -EINVAL; av7110->ci_slot[info->num].num = info->num; av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? -- cgit v1.2.3 From ed887b2eed606d4267e950161d40b9d36154ff30 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 7 Feb 2011 19:20:55 +0000 Subject: bonding/vlan: Avoid mangled NAs on slaves without VLAN tag insertion This is related to commit f88a4a9b65a6f3422b81be995535d0e69df11bb8 upstream, but the bug cannot be properly fixed without the other changes to VLAN tagging in 2.6.37. bond_na_send() attempts to insert a VLAN tag in between building and sending packets of the respective formats. If the slave does not implement hardware VLAN tag insertion then vlan_put_tag() will mangle the network-layer header because the Ethernet header is not present at this point (unlike in bond_arp_send()). Signed-off-by: Ben Hutchings Acked-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/bonding/bond_ipv6.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/bonding/bond_ipv6.c b/drivers/net/bonding/bond_ipv6.c index 969ffed86b9f..07fa65f5d58a 100644 --- a/drivers/net/bonding/bond_ipv6.c +++ b/drivers/net/bonding/bond_ipv6.c @@ -70,6 +70,13 @@ static void bond_na_send(struct net_device *slave_dev, }; struct sk_buff *skb; + /* The Ethernet header is built in ndisc_send_skb(), not + * ndisc_build_skb(), so we cannot insert a VLAN tag. Only an + * out-of-line tag inserted by the hardware will work. + */ + if (vlan_id && !(slave_dev->features & NETIF_F_HW_VLAN_TX)) + return; + icmp6h.icmp6_router = router; icmp6h.icmp6_solicited = 0; icmp6h.icmp6_override = 1; @@ -88,7 +95,7 @@ static void bond_na_send(struct net_device *slave_dev, } if (vlan_id) { - skb = vlan_put_tag(skb, vlan_id); + skb = __vlan_hwaccel_put_tag(skb, vlan_id); if (!skb) { pr_err("failed to insert VLAN tag\n"); return; -- cgit v1.2.3 From 693f1255cb838ea0504c0faff7374997cb6c8908 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Fri, 4 Feb 2011 18:13:24 +0000 Subject: CRED: Fix kernel panic upon security_file_alloc() failure. commit 78d2978874e4e10e97dfd4fd79db45bdc0748550 upstream. In get_empty_filp() since 2.6.29, file_free(f) is called with f->f_cred == NULL when security_file_alloc() returned an error. As a result, kernel will panic() due to put_cred(NULL) call within RCU callback. Fix this bug by assigning f->f_cred before calling security_file_alloc(). Signed-off-by: Tetsuo Handa Signed-off-by: David Howells Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/file_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/file_table.c b/fs/file_table.c index 5c7d10ead4ad..684ffe3c97ac 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -123,13 +123,13 @@ struct file *get_empty_filp(void) goto fail; percpu_counter_inc(&nr_files); + f->f_cred = get_cred(cred); if (security_file_alloc(f)) goto fail_sec; INIT_LIST_HEAD(&f->f_u.fu_list); atomic_long_set(&f->f_count, 1); rwlock_init(&f->f_owner.lock); - f->f_cred = get_cred(cred); spin_lock_init(&f->f_lock); eventpoll_init_file(f); /* f->f_version: 0 */ -- cgit v1.2.3 From 1e1d5bf10f0ee5550bcbfd14dd944a526a68a93e Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Mon, 7 Feb 2011 13:36:10 +0000 Subject: CRED: Fix BUG() upon security_cred_alloc_blank() failure commit 2edeaa34a6e3f2c43b667f6c4f7b27944b811695 upstream. In cred_alloc_blank() since 2.6.32, abort_creds(new) is called with new->security == NULL and new->magic == 0 when security_cred_alloc_blank() returns an error. As a result, BUG() will be triggered if SELinux is enabled or CONFIG_DEBUG_CREDENTIALS=y. If CONFIG_DEBUG_CREDENTIALS=y, BUG() is called from __invalid_creds() because cred->magic == 0. Failing that, BUG() is called from selinux_cred_free() because selinux_cred_free() is not expecting cred->security == NULL. This does not affect smack_cred_free(), tomoyo_cred_free() or apparmor_cred_free(). Fix these bugs by (1) Set new->magic before calling security_cred_alloc_blank(). (2) Handle null cred->security in creds_are_invalid() and selinux_cred_free(). Signed-off-by: Tetsuo Handa Signed-off-by: David Howells Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/cred.c | 12 ++++++++---- security/selinux/hooks.c | 6 +++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/kernel/cred.c b/kernel/cred.c index 60bc8b1e32e6..7d185fe6379f 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -256,13 +256,13 @@ struct cred *cred_alloc_blank(void) #endif atomic_set(&new->usage, 1); +#ifdef CONFIG_DEBUG_CREDENTIALS + new->magic = CRED_MAGIC; +#endif if (security_cred_alloc_blank(new, GFP_KERNEL) < 0) goto error; -#ifdef CONFIG_DEBUG_CREDENTIALS - new->magic = CRED_MAGIC; -#endif return new; error: @@ -754,7 +754,11 @@ bool creds_are_invalid(const struct cred *cred) if (cred->magic != CRED_MAGIC) return true; #ifdef CONFIG_SECURITY_SELINUX - if (selinux_is_enabled()) { + /* + * cred->security == NULL if security_cred_alloc_blank() or + * security_prepare_creds() returned an error. + */ + if (selinux_is_enabled() && cred->security) { if ((unsigned long) cred->security < PAGE_SIZE) return true; if ((*(u32 *)cred->security & 0xffffff00) == diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 49e55c041fa8..7b765f0c38dd 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3234,7 +3234,11 @@ static void selinux_cred_free(struct cred *cred) { struct task_security_struct *tsec = cred->security; - BUG_ON((unsigned long) cred->security < PAGE_SIZE); + /* + * cred->security == NULL if security_cred_alloc_blank() or + * security_prepare_creds() returned an error. + */ + BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE); cred->security = (void *) 0x7UL; kfree(tsec); } -- cgit v1.2.3 From a633f63ce3ccfae3e15d092a25b19e39dc4b33c4 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Mon, 7 Feb 2011 13:36:16 +0000 Subject: CRED: Fix memory and refcount leaks upon security_prepare_creds() failure commit fb2b2a1d37f80cc818fd4487b510f4e11816e5e1 upstream. In prepare_kernel_cred() since 2.6.29, put_cred(new) is called without assigning new->usage when security_prepare_creds() returned an error. As a result, memory for new and refcount for new->{user,group_info,tgcred} are leaked because put_cred(new) won't call __put_cred() unless old->usage == 1. Fix these leaks by assigning new->usage (and new->subscribers which was added in 2.6.32) before calling security_prepare_creds(). Signed-off-by: Tetsuo Handa Signed-off-by: David Howells Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/cred.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/cred.c b/kernel/cred.c index 7d185fe6379f..a8d12feda053 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -663,6 +663,8 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) validate_creds(old); *new = *old; + atomic_set(&new->usage, 1); + set_cred_subscribers(new, 0); get_uid(new->user); get_group_info(new->group_info); @@ -680,8 +682,6 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) if (security_prepare_creds(new, old, GFP_KERNEL) < 0) goto error; - atomic_set(&new->usage, 1); - set_cred_subscribers(new, 0); put_cred(old); validate_creds(new); return new; -- cgit v1.2.3 From a453138cc592112d08b51ba97c77c8de60c8be91 Mon Sep 17 00:00:00 2001 From: "J. R. Okajima" Date: Wed, 11 Aug 2010 13:10:16 -0400 Subject: NFS: fix the return value of nfs_file_fsync() commit 0702099bd86c33c2dcdbd3963433a61f3f503901 upstream. By the commit af7fa16 2010-08-03 NFS: Fix up the fsync code close(2) became returning the non-zero value even if it went well. nfs_file_fsync() should return 0 when "status" is positive. Signed-off-by: J. R. Okajima Signed-off-by: Trond Myklebust Signed-off-by: Tim Gardner Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 642c819c89cd..6fd4fba4ed76 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -222,7 +222,7 @@ static int nfs_do_fsync(struct nfs_open_context *ctx, struct inode *inode) have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); if (have_error) ret = xchg(&ctx->error, 0); - if (!ret) + if (!ret && status < 0) ret = status; return ret; } -- cgit v1.2.3 From d5ea92235e005b6715ad5acc17f8517134f9571f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 29 Sep 2010 22:16:36 +0200 Subject: isdn: hisax: Replace the bogus access to irq stats commit 40f08a724fcc21285cf3a75aec957aef908605c6 upstream. Abusing irq stats in a driver for counting interrupts is a horrible idea and not safe with shared interrupts. Replace it by a local interrupt counter. Noticed by the attempt to remove the irq stats export. Signed-off-by: Thomas Gleixner Signed-off-by: Andi Kleen Reviewed-by: Ingo Molnar Cc: maximilian attems Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/hisax/config.c | 18 ++++++++++++++---- drivers/isdn/hisax/hisax.h | 1 + 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index 544cf4b1cce3..0a347a8a9eee 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -801,6 +801,16 @@ static void closecard(int cardnr) ll_unload(csta); } +static irqreturn_t card_irq(int intno, void *dev_id) +{ + struct IsdnCardState *cs = dev_id; + irqreturn_t ret = cs->irq_func(intno, cs); + + if (ret == IRQ_HANDLED) + cs->irq_cnt++; + return ret; +} + static int init_card(struct IsdnCardState *cs) { int irq_cnt, cnt = 3, ret; @@ -809,10 +819,10 @@ static int init_card(struct IsdnCardState *cs) ret = cs->cardmsg(cs, CARD_INIT, NULL); return(ret); } - irq_cnt = kstat_irqs(cs->irq); + irq_cnt = cs->irq_cnt = 0; printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], cs->irq, irq_cnt); - if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) { + if (request_irq(cs->irq, card_irq, cs->irq_flags, "HiSax", cs)) { printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n", cs->irq); return 1; @@ -822,8 +832,8 @@ static int init_card(struct IsdnCardState *cs) /* Timeout 10ms */ msleep(10); printk(KERN_INFO "%s: IRQ %d count %d\n", - CardType[cs->typ], cs->irq, kstat_irqs(cs->irq)); - if (kstat_irqs(cs->irq) == irq_cnt) { + CardType[cs->typ], cs->irq, cs->irq_cnt); + if (cs->irq_cnt == irq_cnt) { printk(KERN_WARNING "%s: IRQ(%d) getting no interrupts during init %d\n", CardType[cs->typ], cs->irq, 4 - cnt); diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index 832a87855ffb..32ab3924aa73 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h @@ -959,6 +959,7 @@ struct IsdnCardState { u_long event; struct work_struct tqueue; struct timer_list dbusytimer; + unsigned int irq_cnt; #ifdef ERROR_STATISTIC int err_crc; int err_tx; -- cgit v1.2.3 From 5b0a60bac224665da075691ee6a46bad0581f3cc Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 18 Feb 2010 17:32:03 -0600 Subject: scsi_dh_alua: add netapp to dev list commit cd4a8814d44672bd2c8f04a472121bfbe193809c upstream. Newer Netapp target software supports ALUA, so this patch adds them to the scsi_dev_alua dev list. Signed-off-by: Mike Christie Signed-off-by: James Bottomley Signed-off-by: Andi Kleen Cc: maximilian attems Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/device_handler/scsi_dh_alua.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 1a970a76b1b9..a401ed21d58e 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -720,6 +720,7 @@ static const struct scsi_dh_devlist alua_dev_list[] = { {"Intel", "Multi-Flex"}, {"NETAPP", "LUN"}, {"AIX", "NVDISK"}, + {"NETAPP", "LUN"}, {NULL, NULL} }; -- cgit v1.2.3 From e7063b88e6c51d05ad29dbdf9e610451ee6ba559 Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 19 Feb 2010 10:08:31 -0600 Subject: scsi_dh_alua: Add IBM Power Virtual SCSI ALUA device to dev list commit 22963a37b3437a25812cc856afa5a84ad4a3f541 upstream. Adds IBM Power Virtual SCSI ALUA devices to the ALUA device handler. Signed-off-by: Brian King Signed-off-by: James Bottomley Signed-off-by: Andi Kleen Cc: maximilian attems Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/device_handler/scsi_dh_alua.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index a401ed21d58e..3d9f55f06005 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -721,6 +721,7 @@ static const struct scsi_dh_devlist alua_dev_list[] = { {"NETAPP", "LUN"}, {"AIX", "NVDISK"}, {"NETAPP", "LUN"}, + {"AIX", "NVDISK"}, {NULL, NULL} }; -- cgit v1.2.3 From 06ba304f64519b48c7438e9ab48c74e1f0b772b0 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 16 Feb 2011 13:08:35 +1100 Subject: nfsd: correctly handle return value from nfsd_map_name_to_* commit 47c85291d3dd1a51501555000b90f8e281a0458e upstream. These functions return an nfs status, not a host_err. So don't try to convert before returning. This is a regression introduced by 3c726023402a2f3b28f49b9d90ebf9e71151157d; I fixed up two of the callers, but missed these two. Reported-by: Herbert Poetzl Signed-off-by: NeilBrown Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfsd/nfs4xdr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index ac17a7080239..93ff828c22cc 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -316,8 +316,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, READ_BUF(dummy32); len += (XDR_QUADLEN(dummy32) << 2); READMEM(buf, dummy32); - if ((host_err = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid))) - goto out_nfserr; + if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid))) + return status; iattr->ia_valid |= ATTR_UID; } if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) { @@ -327,8 +327,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, READ_BUF(dummy32); len += (XDR_QUADLEN(dummy32) << 2); READMEM(buf, dummy32); - if ((host_err = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid))) - goto out_nfserr; + if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid))) + return status; iattr->ia_valid |= ATTR_GID; } if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) { -- cgit v1.2.3 From 6736d3bbb4c33f0e99cfdbfb74cbefeda7048c17 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Tue, 15 Feb 2011 09:43:32 +0100 Subject: s390: remove task_show_regs commit 261cd298a8c363d7985e3482946edb4bfedacf98 upstream. task_show_regs used to be a debugging aid in the early bringup days of Linux on s390. /proc//status is a world readable file, it is not a good idea to show the registers of a process. The only correct fix is to remove task_show_regs. Reported-by: Al Viro Signed-off-by: Martin Schwidefsky Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/s390/include/asm/processor.h | 5 ----- arch/s390/kernel/traps.c | 37 ------------------------------------- fs/proc/array.c | 3 --- 3 files changed, 45 deletions(-) diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 73e259834e10..f73b50ae4831 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -150,11 +150,6 @@ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); */ extern unsigned long thread_saved_pc(struct task_struct *t); -/* - * Print register of task into buffer. Used in fs/proc/array.c. - */ -extern void task_show_regs(struct seq_file *m, struct task_struct *task); - extern void show_code(struct pt_regs *regs); unsigned long get_wchan(struct task_struct *p); diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 5d8f0f3d0250..657cb1761ae7 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -237,43 +237,6 @@ void show_regs(struct pt_regs *regs) show_last_breaking_event(regs); } -/* This is called from fs/proc/array.c */ -void task_show_regs(struct seq_file *m, struct task_struct *task) -{ - struct pt_regs *regs; - - regs = task_pt_regs(task); - seq_printf(m, "task: %p, ksp: %p\n", - task, (void *)task->thread.ksp); - seq_printf(m, "User PSW : %p %p\n", - (void *) regs->psw.mask, (void *)regs->psw.addr); - - seq_printf(m, "User GPRS: " FOURLONG, - regs->gprs[0], regs->gprs[1], - regs->gprs[2], regs->gprs[3]); - seq_printf(m, " " FOURLONG, - regs->gprs[4], regs->gprs[5], - regs->gprs[6], regs->gprs[7]); - seq_printf(m, " " FOURLONG, - regs->gprs[8], regs->gprs[9], - regs->gprs[10], regs->gprs[11]); - seq_printf(m, " " FOURLONG, - regs->gprs[12], regs->gprs[13], - regs->gprs[14], regs->gprs[15]); - seq_printf(m, "User ACRS: %08x %08x %08x %08x\n", - task->thread.acrs[0], task->thread.acrs[1], - task->thread.acrs[2], task->thread.acrs[3]); - seq_printf(m, " %08x %08x %08x %08x\n", - task->thread.acrs[4], task->thread.acrs[5], - task->thread.acrs[6], task->thread.acrs[7]); - seq_printf(m, " %08x %08x %08x %08x\n", - task->thread.acrs[8], task->thread.acrs[9], - task->thread.acrs[10], task->thread.acrs[11]); - seq_printf(m, " %08x %08x %08x %08x\n", - task->thread.acrs[12], task->thread.acrs[13], - task->thread.acrs[14], task->thread.acrs[15]); -} - static DEFINE_SPINLOCK(die_lock); void die(const char * str, struct pt_regs * regs, long err) diff --git a/fs/proc/array.c b/fs/proc/array.c index fff6572676ae..3d88fe1b9843 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -353,9 +353,6 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns, task_cap(m, task); task_cpus_allowed(m, task); cpuset_task_status_allowed(m, task); -#if defined(CONFIG_S390) - task_show_regs(m, task); -#endif task_context_switch_counts(m, task); return 0; } -- cgit v1.2.3 From f153f5f88f2a1e5ad38a328b144bd3a5b1f5dca3 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 12 Feb 2011 21:06:51 +0100 Subject: PM / Hibernate: Return error code when alloc_image_page() fails commit 2e725a065b0153f0c449318da1923a120477633d upstream. Currently we return 0 in swsusp_alloc() when alloc_image_page() fails. Fix that. Also remove unneeded "error" variable since the only useful value of error is -ENOMEM. [rjw: Fixed up the changelog and changed subject.] Signed-off-by: Stanislaw Gruszka Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/power/snapshot.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 7fa52b5ce88d..1a9b32607339 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -1512,11 +1512,8 @@ static int swsusp_alloc(struct memory_bitmap *orig_bm, struct memory_bitmap *copy_bm, unsigned int nr_pages, unsigned int nr_highmem) { - int error = 0; - if (nr_highmem > 0) { - error = get_highmem_buffer(PG_ANY); - if (error) + if (get_highmem_buffer(PG_ANY)) goto err_out; if (nr_highmem > alloc_highmem) { nr_highmem -= alloc_highmem; @@ -1539,7 +1536,7 @@ swsusp_alloc(struct memory_bitmap *orig_bm, struct memory_bitmap *copy_bm, err_out: swsusp_free(); - return error; + return -ENOMEM; } asmlinkage int swsusp_save(void) -- cgit v1.2.3 From 7b395dfa721d590bcafaf3f022f3c3a96e9fc218 Mon Sep 17 00:00:00 2001 From: Timo Warns Date: Thu, 17 Feb 2011 22:27:40 +0100 Subject: fs/partitions: Validate map_count in Mac partition tables commit fa7ea87a057958a8b7926c1a60a3ca6d696328ed upstream. Validate number of blocks in map and remove redundant variable. Signed-off-by: Timo Warns Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/partitions/mac.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/fs/partitions/mac.c b/fs/partitions/mac.c index 74465ff7c263..0984d92bcf86 100644 --- a/fs/partitions/mac.c +++ b/fs/partitions/mac.c @@ -29,10 +29,9 @@ static inline void mac_fix_string(char *stg, int len) int mac_partition(struct parsed_partitions *state) { - int slot = 1; Sector sect; unsigned char *data; - int blk, blocks_in_map; + int slot, blocks_in_map; unsigned secsize; #ifdef CONFIG_PPC_PMAC int found_root = 0; @@ -59,10 +58,14 @@ int mac_partition(struct parsed_partitions *state) put_dev_sector(sect); return 0; /* not a MacOS disk */ } - printk(" [mac]"); blocks_in_map = be32_to_cpu(part->map_count); - for (blk = 1; blk <= blocks_in_map; ++blk) { - int pos = blk * secsize; + if (blocks_in_map < 0 || blocks_in_map >= DISK_MAX_PARTS) { + put_dev_sector(sect); + return 0; + } + printk(" [mac]"); + for (slot = 1; slot <= blocks_in_map; ++slot) { + int pos = slot * secsize; put_dev_sector(sect); data = read_part_sector(state, pos/512, §); if (!data) @@ -113,13 +116,11 @@ int mac_partition(struct parsed_partitions *state) } if (goodness > found_root_goodness) { - found_root = blk; + found_root = slot; found_root_goodness = goodness; } } #endif /* CONFIG_PPC_PMAC */ - - ++slot; } #ifdef CONFIG_PPC_PMAC if (found_root_goodness) -- cgit v1.2.3 From 1e1e015ade892234b1b0e487521af07f46117aa5 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Mon, 14 Feb 2011 20:27:44 +0100 Subject: ALSA: HDA: Add position_fix quirk for an Asus device commit b540afc2b3d6e4cd1d1f137ef6d9e9c78d67fecd upstream. The bug reporter claims that position_fix=1 is needed for his microphone to work. The controller PCI vendor-id is [1002:4383] (rev 40). Reported-by: Kjell L. BugLink: http://bugs.launchpad.net/bugs/718402 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/hda_intel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c4c9217394e0..824e220ce9ec 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2300,6 +2300,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), + SND_PCI_QUIRK(0x1043, 0x8410, "ASUS", POS_FIX_LPIB), SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba A100-259", POS_FIX_LPIB), -- cgit v1.2.3 From 2d1db98fe0e20e7e419451e7eef36289cbdc4c68 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 14 Feb 2011 22:45:59 +0100 Subject: ALSA: caiaq - Fix possible string-buffer overflow commit eaae55dac6b64c0616046436b294e69fc5311581 upstream. Use strlcpy() to assure not to overflow the string array sizes by too long USB device name string. Reported-by: Rafa Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/usb/caiaq/audio.c | 2 +- sound/usb/caiaq/midi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index 4328cad6c3a2..a184e9138204 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c @@ -640,7 +640,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev) } dev->pcm->private_data = dev; - strcpy(dev->pcm->name, dev->product_name); + strlcpy(dev->pcm->name, dev->product_name, sizeof(dev->pcm->name)); memset(dev->sub_playback, 0, sizeof(dev->sub_playback)); memset(dev->sub_capture, 0, sizeof(dev->sub_capture)); diff --git a/sound/usb/caiaq/midi.c b/sound/usb/caiaq/midi.c index 2f218c77fff2..a1a47088fd0c 100644 --- a/sound/usb/caiaq/midi.c +++ b/sound/usb/caiaq/midi.c @@ -136,7 +136,7 @@ int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device) if (ret < 0) return ret; - strcpy(rmidi->name, device->product_name); + strlcpy(rmidi->name, device->product_name, sizeof(rmidi->name)); rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX; rmidi->private_data = device; -- cgit v1.2.3 From 6f1b1e1384b23cfab30c2bc02a8f94927274c10d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 16 Jan 2011 10:09:13 -0300 Subject: radio-aimslab.c needs #include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 2400982a2e8a8e4e95f0a0e1517bbe63cc88038f upstream. Commit e3c92215198cb6aa00ad38db2780faa6b72e0a3f ("[media] radio-aimslab.c: Fix gcc 4.5+ bug") removed the include, but introduced new callers of msleep(): | drivers/media/radio/radio-aimslab.c: In function ‘rt_decvol’: | drivers/media/radio/radio-aimslab.c:76: error: implicit declaration of function ‘msleep’ Signed-off-by: Geert Uytterhoeven Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andi Kleen Cc: dann frazier Signed-off-by: Greg Kroah-Hartman --- drivers/media/radio/radio-aimslab.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 19448144eb3a..a91642cd9222 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -31,6 +31,7 @@ #include /* Modules */ #include /* Initdata */ #include /* request_region */ +#include /* msleep */ #include /* kernel radio structs */ #include /* for KERNEL_VERSION MACRO */ #include /* outb, outb_p */ -- cgit v1.2.3 From 7d13ddf6579f7a201201765315cf1a969226dde7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 20 Feb 2011 12:22:52 +0000 Subject: ARM: Ensure predictable endian state on signal handler entry commit 53399053eb505cf541b2405bd9d9bca5ecfb96fb upstream. Ensure a predictable endian state when entering signal handlers. This avoids programs which use SETEND to momentarily switch their endian state from having their signal handlers entered with an unpredictable endian state. Acked-by: Dave Martin Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/arm/kernel/signal.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 907d5a620bca..abaf8445ce25 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -474,7 +474,9 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka, unsigned long handler = (unsigned long)ka->sa.sa_handler; unsigned long retcode; int thumb = 0; - unsigned long cpsr = regs->ARM_cpsr & ~PSR_f; + unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT); + + cpsr |= PSR_ENDSTATE; /* * Maybe we need to deliver a 32-bit signal to a 26-bit task. -- cgit v1.2.3 From fe5d03ded1703844bb0d05219a4de9d071b7046b Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 9 Feb 2011 16:39:40 -0500 Subject: acer-wmi: Fix capitalisation of GUID commit bbb706079abe955a9e3f208f541de97d99449236 upstream. 6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3 needs to be 6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3 to match the hardware alias. Signed-off-by: Matthew Garrett Acked-by: Carlos Corbacho Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/platform/x86/acer-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 1ea6c434d330..9fa264386f88 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -91,7 +91,7 @@ struct acer_quirks { */ #define AMW0_GUID1 "67C3371D-95A3-4C37-BB61-DD47B491DAAB" #define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C" -#define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3" +#define WMID_GUID1 "6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3" #define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A" MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB"); -- cgit v1.2.3 From de009baa36ee44f5218220a1a8b41153b68a4cb5 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Tue, 11 Jan 2011 12:43:42 -0600 Subject: eCryptfs: Copy up lower inode attrs in getattr commit 55f9cf6bbaa682958a7dd2755f883b768270c3ce upstream. The lower filesystem may do some type of inode revalidation during a getattr call. eCryptfs should take advantage of that by copying the lower inode attributes to the eCryptfs inode after a call to vfs_getattr() on the lower inode. I originally wrote this fix while working on eCryptfs on nfsv3 support, but discovered it also fixed an eCryptfs on ext4 nanosecond timestamp bug that was reported. https://bugs.launchpad.net/bugs/613873 Signed-off-by: Tyler Hicks Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ecryptfs/inode.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index db9feb54d273..1681c620884b 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -1003,6 +1003,8 @@ int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry, rc = vfs_getattr(ecryptfs_dentry_to_lower_mnt(dentry), ecryptfs_dentry_to_lower(dentry), &lower_stat); if (!rc) { + fsstack_copy_attr_all(dentry->d_inode, + ecryptfs_inode_to_lower(dentry->d_inode)); generic_fillattr(dentry->d_inode, stat); stat->blocks = lower_stat.blocks; } -- cgit v1.2.3 From 2e5582d2831f77f20862dc0b66b1f0cbb1a03883 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Fri, 4 Feb 2011 15:23:56 +0300 Subject: platform: x86: acer-wmi: world-writable sysfs threeg file commit b80b168f918bba4b847e884492415546b340e19d upstream. Don't allow everybody to write to hardware registers. Signed-off-by: Vasiliy Kulikov Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/platform/x86/acer-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 9fa264386f88..7b32e9c5f5d4 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1066,7 +1066,7 @@ static ssize_t set_bool_threeg(struct device *dev, return -EINVAL; return count; } -static DEVICE_ATTR(threeg, S_IWUGO | S_IRUGO | S_IWUSR, show_bool_threeg, +static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg, set_bool_threeg); static ssize_t show_interface(struct device *dev, struct device_attribute *attr, -- cgit v1.2.3 From 1f6b585a2e843e9ed52f8d5861db3247bdf8b555 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Fri, 4 Feb 2011 15:23:59 +0300 Subject: platform: x86: asus_acpi: world-writable procfs files commit 8040835760adf0ef66876c063d47f79f015fb55d upstream. Don't allow everybody to change ACPI settings. The comment says that it is done deliberatelly, however, the comment before disp_proc_write() says that at least one of these setting is experimental. Signed-off-by: Vasiliy Kulikov Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/platform/x86/asus_acpi.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c index 92fd30c9379c..9727b8e51fd5 100644 --- a/drivers/platform/x86/asus_acpi.c +++ b/drivers/platform/x86/asus_acpi.c @@ -1079,14 +1079,8 @@ static int asus_hotk_add_fs(struct acpi_device *device) struct proc_dir_entry *proc; mode_t mode; - /* - * If parameter uid or gid is not changed, keep the default setting for - * our proc entries (-rw-rw-rw-) else, it means we care about security, - * and then set to -rw-rw---- - */ - if ((asus_uid == 0) && (asus_gid == 0)) { - mode = S_IFREG | S_IRUGO | S_IWUGO; + mode = S_IFREG | S_IRUGO | S_IWUSR | S_IWGRP; } else { mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP; printk(KERN_WARNING " asus_uid and asus_gid parameters are " -- cgit v1.2.3 From 1cbbd0b3c5ea7e636b3fde195c84be9be576d089 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Fri, 4 Feb 2011 15:24:03 +0300 Subject: platform: x86: tc1100-wmi: world-writable sysfs wireless and jogdial files commit 8a6a142c1286797978e4db266d22875a5f424897 upstream. Don't allow everybody to change WMI settings. Signed-off-by: Vasiliy Kulikov Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/platform/x86/tc1100-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/tc1100-wmi.c b/drivers/platform/x86/tc1100-wmi.c index 1fe0f1feff71..865ef78d6f1a 100644 --- a/drivers/platform/x86/tc1100-wmi.c +++ b/drivers/platform/x86/tc1100-wmi.c @@ -162,7 +162,7 @@ set_bool_##value(struct device *dev, struct device_attribute *attr, \ return -EINVAL; \ return count; \ } \ -static DEVICE_ATTR(value, S_IWUGO | S_IRUGO | S_IWUSR, \ +static DEVICE_ATTR(value, S_IRUGO | S_IWUSR, \ show_bool_##value, set_bool_##value); show_set_bool(wireless, TC1100_INSTANCE_WIRELESS); -- cgit v1.2.3 From 2227ae957ac60b70dadec05d1bb5e57cb084e131 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 18 Feb 2011 23:27:23 +0100 Subject: genirq: Disable the SHIRQ_DEBUG call in request_threaded_irq for now commit 6d83f94db95cfe65d2a6359cccdf61cf087c2598 upstream. With CONFIG_SHIRQ_DEBUG=y we call a newly installed interrupt handler in request_threaded_irq(). The original implementation (commit a304e1b8) called the handler _BEFORE_ it was installed, but that caused problems with handlers calling disable_irq_nosync(). See commit 377bf1e4. It's braindead in the first place to call disable_irq_nosync in shared handlers, but .... Moving this call after we installed the handler looks innocent, but it is very subtle broken on SMP. Interrupt handlers rely on the fact, that the irq core prevents reentrancy. Now this debug call violates that promise because we run the handler w/o the IRQ_INPROGRESS protection - which we cannot apply here because that would result in a possibly forever masked interrupt line. A concurrent real hardware interrupt on a different CPU results in handler reentrancy and can lead to complete wreckage, which was unfortunately observed in reality and took a fricking long time to debug. Leave the code here for now. We want this debug feature, but that's not easy to fix. We really should get rid of those disable_irq_nosync() abusers and remove that function completely. Signed-off-by: Thomas Gleixner Signed-off-by: Andi Kleen Cc: Anton Vorontsov Cc: David Woodhouse Cc: Arjan van de Ven Signed-off-by: Greg Kroah-Hartman --- kernel/irq/manage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index c3003e9d91a3..6a2281f781c1 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -1093,7 +1093,7 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler, if (retval) kfree(action); -#ifdef CONFIG_DEBUG_SHIRQ +#ifdef CONFIG_DEBUG_SHIRQ_FIXME if (!retval && (irqflags & IRQF_SHARED)) { /* * It's a shared IRQ -- the driver ought to be prepared for it -- cgit v1.2.3 From be8787645695b75ac654b322b72f8e529ef1e728 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 11 Feb 2011 16:57:08 +0100 Subject: usb: musb: omap2430: fix kernel panic on reboot commit b193b412e62b134adf69af286c7e7f8e99259350 upstream. Cancel idle timer in musb_platform_exit. The idle timer could trigger after clock had been disabled leading to kernel panic when MUSB_DEVCTL is accessed in musb_do_idle on 2.6.37. The fault below is no longer triggered on 2.6.38-rc4 (clock is disabled later, and only if compiled as a module, and the offending memory access has moved) but the timer should be cancelled nonetheless. Rebooting... musb_hdrc musb_hdrc: remove, state 4 usb usb1: USB disconnect, address 1 musb_hdrc musb_hdrc: USB bus 1 deregistered Unhandled fault: external abort on non-linefetch (0x1028) at 0xfa0ab060 Internal error: : 1028 [#1] PREEMPT last sysfs file: /sys/kernel/uevent_seqnum Modules linked in: CPU: 0 Not tainted (2.6.37+ #6) PC is at musb_do_idle+0x24/0x138 LR is at musb_do_idle+0x18/0x138 pc : [] lr : [] psr: 80000193 sp : cf2bdd80 ip : cf2bdd80 fp : c048a20c r10: c048a60c r9 : c048a40c r8 : cf85e110 r7 : cf2bc000 r6 : 40000113 r5 : c0489800 r4 : cf85e110 r3 : 00000004 r2 : 00000006 r1 : fa0ab000 r0 : cf8a7000 Flags: Nzcv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user Control: 10c5387d Table: 8faac019 DAC: 00000015 Process reboot (pid: 769, stack limit = 0xcf2bc2f0) Stack: (0xcf2bdd80 to 0xcf2be000) dd80: 00000103 c0489800 c02377b4 c005fa34 00000555 c0071a8c c04a3858 cf2bdda8 dda0: 00000555 c048a00c cf2bdda8 cf2bdda8 1838beb0 00000103 00000004 cf2bc000 ddc0: 00000001 00000001 c04896c8 0000000a 00000000 c005ac14 00000001 c003f32c dde0: 00000000 00000025 00000000 cf2bc000 00000002 00000001 cf2bc000 00000000 de00: 00000001 c005ad08 cf2bc000 c002e07c c03ec039 ffffffff fa200000 c0033608 de20: 00000001 00000000 cf852c14 cf81f200 c045b714 c045b708 cf2bc000 c04a37e8 de40: c0033c04 cf2bc000 00000000 00000001 cf2bde68 cf2bde68 c01c3abc c004f7d8 de60: 60000013 ffffffff c0033c04 00000000 01234567 fee1dead 00000000 c006627c de80: 00000001 c00662c8 28121969 c00663ec cfa38c40 cf9f6a00 cf2bded0 cf9f6a0c dea0: 00000000 cf92f000 00008914 c02cd284 c04a55c8 c028b398 c00715c0 becf24a8 dec0: 30687465 00000000 00000000 00000000 00000002 1301a8c0 00000000 00000000 dee0: 00000002 1301a8c0 00000000 00000000 c0450494 cf527920 00011f10 cf2bdf08 df00: 00011f10 cf2bdf10 00011f10 cf2bdf18 c00f0b44 c004f7e8 cf2bdf18 cf2bdf18 df20: 00011f10 cf2bdf30 00011f10 cf2bdf38 cf401300 cf486100 00000008 c00d2b28 df40: 00011f10 cf401300 00200200 c00d3388 00011f10 cfb63a88 cfb63a80 c00c2f08 df60: 00000000 00000000 cfb63a80 00000000 cf0a3480 00000006 c0033c04 cfb63a80 df80: 00000000 c00c0104 00000003 cf0a3480 cfb63a80 00000000 00000001 00000004 dfa0: 00000058 c0033a80 00000000 00000001 fee1dead 28121969 01234567 00000000 dfc0: 00000000 00000001 00000004 00000058 00000001 00000001 00000000 00000001 dfe0: 4024d200 becf2cb0 00009210 4024d218 60000010 fee1dead 00000000 00000000 [] (musb_do_idle+0x24/0x138) from [] (run_timer_softirq+0x1a8/0x26) [] (run_timer_softirq+0x1a8/0x26c) from [] (__do_softirq+0x88/0x13) [] (__do_softirq+0x88/0x138) from [] (irq_exit+0x44/0x98) [] (irq_exit+0x44/0x98) from [] (asm_do_IRQ+0x7c/0xa0) [] (asm_do_IRQ+0x7c/0xa0) from [] (__irq_svc+0x48/0xa8) Exception stack(0xcf2bde20 to 0xcf2bde68) de20: 00000001 00000000 cf852c14 cf81f200 c045b714 c045b708 cf2bc000 c04a37e8 de40: c0033c04 cf2bc000 00000000 00000001 cf2bde68 cf2bde68 c01c3abc c004f7d8 de60: 60000013 ffffffff [] (__irq_svc+0x48/0xa8) from [] (sub_preempt_count+0x0/0xb8) Code: ebf86030 e5940098 e594108c e5902010 (e5d13060) Signed-off-by: Andi Kleen ---[ end trace 3689c0d808f9bf7c ]--- Kernel panic - not syncing: Fatal exception in interrupt Signed-off-by: Johan Hovold Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/omap2430.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index d57d9a412a8a..49352b30c849 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -323,6 +323,7 @@ static int musb_platform_resume(struct musb *musb) int musb_platform_exit(struct musb *musb) { + del_timer_sync(&musb_idle_timer); musb_platform_suspend(musb); -- cgit v1.2.3 From ff91c7c848902af82f0bbf428038a9b08d0e8d7c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 17 Feb 2011 10:26:38 -0500 Subject: USB: add quirks entry for Keytouch QWERTY Panel commit 3c18e30f87ac5466bddbb05cf955605efd7db025 upstream. This patch (as1448) adds a quirks entry for the Keytouch QWERTY Panel firmware, used in the IEC 60945 keyboard. This device crashes during enumeration when the computer asks for its configuration string descriptor. Signed-off-by: Alan Stern Tested-by: kholis Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/core/quirks.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 25719da45e33..c456ce0920eb 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -68,6 +68,10 @@ static const struct usb_device_id usb_quirk_list[] = { /* M-Systems Flash Disk Pioneers */ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Keytouch QWERTY Panel keyboard */ + { USB_DEVICE(0x0926, 0x3333), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, + /* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */ { USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF }, -- cgit v1.2.3 From 5a67c8ece38ca56d2efa725691e6b191fe6dfbaa Mon Sep 17 00:00:00 2001 From: Maciej Szmigiero Date: Mon, 7 Feb 2011 12:42:36 +0100 Subject: USB: Add Samsung SGH-I500/Android modem ID switch to visor driver commit acb52cb1613e1d3c8a8c650717cc51965c60d7d4 upstream. [USB]Add Samsung SGH-I500/Android modem ID switch to visor driver Samsung decided to reuse USB ID of its old CDMA phone SGH-I500 for the modem part of some of their Android phones. At least Galaxy Spica is affected. This modem needs ACM driver and does not work with visor driver which binds the conflicting ID for SGH-I500. Because SGH-I500 is pretty an old hardware its best to add switch to visor driver in cause somebody still wants to use that phone with Linux. Note that this is needed only when using the Android phone as modem, not in USB storage or ADB mode. Signed-off-by: Maciej Szmigiero Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/visor.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 15a5d89b7f39..1c11959a7d58 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "visor.h" /* @@ -479,6 +480,17 @@ static int visor_probe(struct usb_serial *serial, dbg("%s", __func__); + /* + * some Samsung Android phones in modem mode have the same ID + * as SPH-I500, but they are ACM devices, so dont bind to them + */ + if (id->idVendor == SAMSUNG_VENDOR_ID && + id->idProduct == SAMSUNG_SPH_I500_ID && + serial->dev->descriptor.bDeviceClass == USB_CLASS_COMM && + serial->dev->descriptor.bDeviceSubClass == + USB_CDC_SUBCLASS_ACM) + return -ENODEV; + if (serial->dev->actconfig->desc.bConfigurationValue != 1) { dev_err(&serial->dev->dev, "active config #%d != 1 ??\n", serial->dev->actconfig->desc.bConfigurationValue); -- cgit v1.2.3 From cdb645bdea66542d53216b6c85483b7b6dfd8472 Mon Sep 17 00:00:00 2001 From: Maciej Szmigiero Date: Sat, 5 Feb 2011 21:52:00 +0100 Subject: USB: Add quirk for Samsung Android phone modem commit 72a012ce0a02c6c616676a24b40ff81d1aaeafda upstream. My Galaxy Spica needs this quirk when in modem mode, otherwise it causes endless USB bus resets and is unusable in this mode. Unfortunately Samsung decided to reuse ID of its old CDMA phone SGH-I500 for the modem part. That's why in addition to this patch the visor driver must be prevented from binding to SPH-I500 ID, so ACM driver can do that. Signed-off-by: Maciej Szmigiero Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/core/quirks.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index c456ce0920eb..1848420d98ef 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -48,6 +48,10 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x04b4, 0x0526), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, + /* Samsung Android phone modem - ID conflict with SPH-I500 */ + { USB_DEVICE(0x04e8, 0x6601), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, + /* Roland SC-8820 */ { USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME }, -- cgit v1.2.3 From db07f6d4d8cfc7cf067075d0d8d77bb10abe9282 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 11 Feb 2011 01:48:42 +0100 Subject: p54pci: update receive dma buffers before and after processing commit 0bf719dfdecc5552155cbec78e49fa06e531e35c upstream. Documentation/DMA-API-HOWTO.txt states: "DMA transfers need to be synced properly in order for the cpu and device to see the most uptodate and correct copy of the DMA buffer." Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/p54/p54pci.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index a5ea89cde8c4..a66b39bdf95e 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -199,6 +199,7 @@ static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index, while (i != idx) { u16 len; struct sk_buff *skb; + dma_addr_t dma_addr; desc = &ring[i]; len = le16_to_cpu(desc->len); skb = rx_buf[i]; @@ -216,17 +217,20 @@ static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index, len = priv->common.rx_mtu; } + dma_addr = le32_to_cpu(desc->host_addr); + pci_dma_sync_single_for_cpu(priv->pdev, dma_addr, + priv->common.rx_mtu + 32, PCI_DMA_FROMDEVICE); skb_put(skb, len); if (p54_rx(dev, skb)) { - pci_unmap_single(priv->pdev, - le32_to_cpu(desc->host_addr), - priv->common.rx_mtu + 32, - PCI_DMA_FROMDEVICE); + pci_unmap_single(priv->pdev, dma_addr, + priv->common.rx_mtu + 32, PCI_DMA_FROMDEVICE); rx_buf[i] = NULL; - desc->host_addr = 0; + desc->host_addr = cpu_to_le32(0); } else { skb_trim(skb, 0); + pci_dma_sync_single_for_device(priv->pdev, dma_addr, + priv->common.rx_mtu + 32, PCI_DMA_FROMDEVICE); desc->len = cpu_to_le16(priv->common.rx_mtu + 32); } -- cgit v1.2.3 From 42aa554be97de7c9d15aae76a9f9200de25823a7 Mon Sep 17 00:00:00 2001 From: Jon Thomas Date: Wed, 16 Feb 2011 11:02:34 -0500 Subject: sierra: add new ID for Airprime/Sierra USB IP modem commit e1dc5157c574e7249dc1cd072fde2e48b3011533 upstream. I picked up a new Sierra usb 308 (At&t Shockwave) on 2/2011 and the vendor code is 0x0f3d Looking up vendor and product id's I see: 0f3d Airprime, Incorporated 0112 CDMA 1xEVDO PC Card, PC 5220 Sierra and Airprime are somehow related and I'm guessing the At&t usb 308 might be have some common hardware with the AirPrime SL809x. Signed-off-by: Jon Thomas Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/sierra.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index d47b56e9e8ce..d876bba32065 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -302,7 +302,9 @@ static const struct usb_device_id id_table[] = { .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist }, { USB_DEVICE(0x413C, 0x08133) }, /* Dell Computer Corp. Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port */ - + { USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */ + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, { } }; MODULE_DEVICE_TABLE(usb, id_table); -- cgit v1.2.3 From 1c8d316294916da7e2a2f1f178ca3f3bd6d7b531 Mon Sep 17 00:00:00 2001 From: Max Vozeler Date: Wed, 12 Jan 2011 15:02:00 +0200 Subject: staging: usbip: vhci: update reference count for usb_device commit 7606ee8aa33287dd3e6eb44c78541b87a413a325 upstream. This fixes an oops observed when reading status during removal of a device: [ 1706.648285] general protection fault: 0000 [#1] SMP [ 1706.648294] last sysfs file: /sys/devices/platform/vhci_hcd/status [ 1706.648297] CPU 1 [ 1706.648300] Modules linked in: binfmt_misc microcode fuse loop vhci_hcd(N) usbip(N) usbcore usbip_common_mod(N) rtc_core rtc_lib joydev dm_mirror dm_region_hash dm_log linear dm_snapshot xennet dm_mod ext3 mbcache jbd processor thermal_sys hwmon xenblk cdrom [ 1706.648324] Supported: Yes [ 1706.648327] Pid: 10422, comm: usbip Tainted: G N 2.6.32.12-0.7-xen #1 [ 1706.648330] RIP: e030:[] [] strnlen+0x5/0x40 [ 1706.648340] RSP: e02b:ffff8800a994dd30 EFLAGS: 00010286 [ 1706.648343] RAX: ffffffff80481ec1 RBX: 0000000000000000 RCX: 0000000000000002 [ 1706.648347] RDX: 00200d1d4f1c001c RSI: ffffffffffffffff RDI: 00200d1d4f1c001c [ 1706.648350] RBP: ffff880129a1c0aa R08: ffffffffa01901c4 R09: 0000000000000006 [ 1706.648353] R10: 0000000000000000 R11: 0000000000000000 R12: ffff8800a9a1c0ab [ 1706.648357] R13: 00200d1d4f1c001c R14: 00000000ffffffff R15: ffff880129a1c0aa [ 1706.648363] FS: 00007f2f2e9ca700(0000) GS:ffff880001018000(0000) knlGS:0000000000000000 [ 1706.648367] CS: e033 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1706.648370] CR2: 000000000071b048 CR3: 00000000b4b68000 CR4: 0000000000002660 [ 1706.648374] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 1706.648378] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 1706.648381] Process usbip (pid: 10422, threadinfo ffff8800a994c000, task ffff88007b170200) [ 1706.648385] Stack: [ 1706.648387] ffffffff801b28c9 0000000000000002 ffffffffa01901c4 ffff8800a9a1c0ab [ 1706.648391] <0> ffffffffa01901c6 ffff8800a994de08 ffffffff801b339b 0000000000000004 [ 1706.648397] <0> 0000000affffffff ffffffffffffffff 00000000000067c0 0000000000000000 [ 1706.648404] Call Trace: [ 1706.648413] [] string+0x39/0xe0 [ 1706.648419] [] vsnprintf+0x1eb/0x620 [ 1706.648423] [] sprintf+0x43/0x50 [ 1706.648429] [] show_status+0x1b9/0x220 [vhci_hcd] [ 1706.648438] [] dev_attr_show+0x27/0x60 [ 1706.648445] [] sysfs_read_file+0x101/0x1d0 [ 1706.648451] [] vfs_read+0xc7/0x130 [ 1706.648457] [] sys_read+0x53/0xa0 [ 1706.648462] [] system_call_fastpath+0x16/0x1b [ 1706.648468] [<00007f2f2de40f30>] 0x7f2f2de40f30 [ 1706.648470] Code: 66 0f 1f 44 00 00 48 83 c2 01 80 3a 00 75 f7 48 89 d0 48 29 f8 f3 c3 66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 48 85 f6 74 29 <80> 3f 00 74 24 48 8d 56 ff 48 89 f8 eb 0e 0f 1f 44 00 00 48 83 [ 1706.648507] RIP [] strnlen+0x5/0x40 [ 1706.648511] RSP [ 1706.649575] ---[ end trace b4eb72bf2e149593 ]--- Signed-off-by: Max Vozeler Tested-by: Mark Wehby Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/usbip/vhci_hcd.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index 8caa1e305981..d1e56ce42ae0 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -607,7 +607,9 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, dev_info(dev, "SetAddress Request (%d) to port %d\n", ctrlreq->wValue, vdev->rhport); - vdev->udev = urb->dev; + if (vdev->udev) + usb_put_dev(vdev->udev); + vdev->udev = usb_get_dev(urb->dev); spin_lock(&vdev->ud.lock); vdev->ud.status = VDEV_ST_USED; @@ -627,8 +629,9 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, "Get_Descriptor to device 0 " "(get max pipe size)\n"); - /* FIXME: reference count? (usb_get_dev()) */ - vdev->udev = urb->dev; + if (vdev->udev) + usb_put_dev(vdev->udev); + vdev->udev = usb_get_dev(urb->dev); goto out; default: @@ -887,6 +890,10 @@ static void vhci_device_reset(struct usbip_device *ud) vdev->speed = 0; vdev->devid = 0; + if (vdev->udev) + usb_put_dev(vdev->udev); + vdev->udev = NULL; + ud->tcp_socket = NULL; ud->status = VDEV_ST_NULL; -- cgit v1.2.3 From 9f19953fd27806290a9943631ba2fdfd9edb8d0e Mon Sep 17 00:00:00 2001 From: Max Vozeler Date: Wed, 12 Jan 2011 15:02:01 +0200 Subject: staging: usbip: vhci: give back URBs from in-flight unlink requests commit b92a5e23737172c52656a090977408a80d7f06d1 upstream. If we never received a RET_UNLINK because the TCP connection broke the pending URBs still need to be unlinked and given back. Previously processes would be stuck trying to kill the URB even after the device was detached. Signed-off-by: Max Vozeler Tested-by: Mark Wehby Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/usbip/vhci.h | 3 +++ drivers/staging/usbip/vhci_hcd.c | 24 +++++++++++++++++++++++- drivers/staging/usbip/vhci_rx.c | 15 +++++++++------ 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/drivers/staging/usbip/vhci.h b/drivers/staging/usbip/vhci.h index 41a1fe5138f4..2cfd00ec1164 100644 --- a/drivers/staging/usbip/vhci.h +++ b/drivers/staging/usbip/vhci.h @@ -119,6 +119,9 @@ void rh_port_disconnect(int rhport); void vhci_rx_loop(struct usbip_task *ut); void vhci_tx_loop(struct usbip_task *ut); +struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, + __u32 seqnum); + #define hardware (&the_controller->pdev.dev) static inline struct vhci_device *port_to_vdev(__u32 port) diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index d1e56ce42ae0..66a12530eb4f 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -808,7 +808,6 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) return 0; } - static void vhci_device_unlink_cleanup(struct vhci_device *vdev) { struct vhci_unlink *unlink, *tmp; @@ -816,11 +815,34 @@ static void vhci_device_unlink_cleanup(struct vhci_device *vdev) spin_lock(&vdev->priv_lock); list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { + usbip_uinfo("unlink cleanup tx %lu\n", unlink->unlink_seqnum); list_del(&unlink->list); kfree(unlink); } list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { + struct urb *urb; + + /* give back URB of unanswered unlink request */ + usbip_uinfo("unlink cleanup rx %lu\n", unlink->unlink_seqnum); + + urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); + if (!urb) { + usbip_uinfo("the urb (seqnum %lu) was already given back\n", + unlink->unlink_seqnum); + list_del(&unlink->list); + kfree(unlink); + continue; + } + + urb->status = -ENODEV; + + spin_lock(&the_controller->lock); + usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); + spin_unlock(&the_controller->lock); + + usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); + list_del(&unlink->list); kfree(unlink); } diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c index 8147d7202b2d..bdbedd256903 100644 --- a/drivers/staging/usbip/vhci_rx.c +++ b/drivers/staging/usbip/vhci_rx.c @@ -23,16 +23,14 @@ #include "vhci.h" -/* get URB from transmitted urb queue */ -static struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, +/* get URB from transmitted urb queue. caller must hold vdev->priv_lock */ +struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum) { struct vhci_priv *priv, *tmp; struct urb *urb = NULL; int status; - spin_lock(&vdev->priv_lock); - list_for_each_entry_safe(priv, tmp, &vdev->priv_rx, list) { if (priv->seqnum == seqnum) { urb = priv->urb; @@ -63,8 +61,6 @@ static struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, } } - spin_unlock(&vdev->priv_lock); - return urb; } @@ -74,9 +70,11 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, struct usbip_device *ud = &vdev->ud; struct urb *urb; + spin_lock(&vdev->priv_lock); urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); + spin_unlock(&vdev->priv_lock); if (!urb) { usbip_uerr("cannot find a urb of seqnum %u\n", @@ -161,7 +159,12 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, return; } + spin_lock(&vdev->priv_lock); + urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); + + spin_unlock(&vdev->priv_lock); + if (!urb) { /* * I get the result of a unlink request. But, it seems that I -- cgit v1.2.3 From 8ff66f1d0cbdce0a50d7db47863f610b3c45f9e0 Mon Sep 17 00:00:00 2001 From: Max Vozeler Date: Wed, 12 Jan 2011 15:02:02 +0200 Subject: staging: usbip: vhci: refuse to enqueue for dead connections commit 6d212153a838354078cc7d96f9bb23b7d1fd3d1b upstream. There can be requests to enqueue URBs while we are shutting down a connection. Signed-off-by: Max Vozeler Tested-by: Mark Wehby Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/usbip/vhci_hcd.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index 66a12530eb4f..35b9868d8d12 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -559,6 +559,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, struct device *dev = &urb->dev->dev; int ret = 0; unsigned long flags; + struct vhci_device *vdev; usbip_dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n", hcd, urb, mem_flags); @@ -574,6 +575,18 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, return urb->status; } + vdev = port_to_vdev(the_controller->pending_port); + + /* refuse enqueue for dead connection */ + spin_lock(&vdev->ud.lock); + if (vdev->ud.status == VDEV_ST_NULL || vdev->ud.status == VDEV_ST_ERROR) { + usbip_uerr("enqueue for inactive port %d\n", vdev->rhport); + spin_unlock(&vdev->ud.lock); + spin_unlock_irqrestore(&the_controller->lock, flags); + return -ENODEV; + } + spin_unlock(&vdev->ud.lock); + ret = usb_hcd_link_urb_to_ep(hcd, urb); if (ret) goto no_need_unlink; @@ -592,8 +605,6 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, __u8 type = usb_pipetype(urb->pipe); struct usb_ctrlrequest *ctrlreq = (struct usb_ctrlrequest *) urb->setup_packet; - struct vhci_device *vdev = - port_to_vdev(the_controller->pending_port); if (type != PIPE_CONTROL || !ctrlreq) { dev_err(dev, "invalid request to devnum 0\n"); -- cgit v1.2.3 From 0ba1a33e1e67b555104cb586454fbcffba88635d Mon Sep 17 00:00:00 2001 From: Max Vozeler Date: Wed, 12 Jan 2011 15:02:05 +0200 Subject: staging: usbip: vhci: use urb->dev->portnum to find port commit 01446ef5af4e8802369bf4d257806e24345a9371 upstream. The access to pending_port was racy when two devices were being attached at the same time. Signed-off-by: Max Vozeler Tested-by: Mark Wehby Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/usbip/vhci.h | 3 --- drivers/staging/usbip/vhci_hcd.c | 4 +--- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/usbip/vhci.h b/drivers/staging/usbip/vhci.h index 2cfd00ec1164..afc3b1a71881 100644 --- a/drivers/staging/usbip/vhci.h +++ b/drivers/staging/usbip/vhci.h @@ -100,9 +100,6 @@ struct vhci_hcd { * But, the index of this array begins from 0. */ struct vhci_device vdev[VHCI_NPORTS]; - - /* vhci_device which has not been assiged its address yet */ - int pending_port; }; diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index 35b9868d8d12..e003bebd8fa5 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -138,8 +138,6 @@ void rh_port_connect(int rhport, enum usb_device_speed speed) * the_controller->vdev[rhport].ud.status = VDEV_CONNECT; * spin_unlock(&the_controller->vdev[rhport].ud.lock); */ - the_controller->pending_port = rhport; - spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_poll_rh_status(vhci_to_hcd(the_controller)); @@ -575,7 +573,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, return urb->status; } - vdev = port_to_vdev(the_controller->pending_port); + vdev = port_to_vdev(urb->dev->portnum-1); /* refuse enqueue for dead connection */ spin_lock(&vdev->ud.lock); -- cgit v1.2.3 From 0eccd188cfeaf857a26f2d72941d27d298cf6a54 Mon Sep 17 00:00:00 2001 From: Davide Libenzi Date: Fri, 25 Feb 2011 14:44:12 -0800 Subject: epoll: prevent creating circular epoll structures commit 22bacca48a1755f79b7e0f192ddb9fbb7fc6e64e upstream. In several places, an epoll fd can call another file's ->f_op->poll() method with ep->mtx held. This is in general unsafe, because that other file could itself be an epoll fd that contains the original epoll fd. The code defends against this possibility in its own ->poll() method using ep_call_nested, but there are several other unsafe calls to ->poll elsewhere that can be made to deadlock. For example, the following simple program causes the call in ep_insert recursively call the original fd's ->poll, leading to deadlock: #include #include int main(void) { int e1, e2, p[2]; struct epoll_event evt = { .events = EPOLLIN }; e1 = epoll_create(1); e2 = epoll_create(2); pipe(p); epoll_ctl(e2, EPOLL_CTL_ADD, e1, &evt); epoll_ctl(e1, EPOLL_CTL_ADD, p[0], &evt); write(p[1], p, sizeof p); epoll_ctl(e1, EPOLL_CTL_ADD, e2, &evt); return 0; } On insertion, check whether the inserted file is itself a struct epoll, and if so, do a recursive walk to detect whether inserting this file would create a loop of epoll structures, which could lead to deadlock. [nelhage@ksplice.com: Use epmutex to serialize concurrent inserts] Signed-off-by: Davide Libenzi Signed-off-by: Nelson Elhage Signed-off-by: Andi Kleen Reported-by: Nelson Elhage Tested-by: Nelson Elhage Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/eventpoll.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 3817149919cb..25bcbd19f5eb 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -63,6 +63,13 @@ * cleanup path and it is also acquired by eventpoll_release_file() * if a file has been pushed inside an epoll set and it is then * close()d without a previous call toepoll_ctl(EPOLL_CTL_DEL). + * It is also acquired when inserting an epoll fd onto another epoll + * fd. We do this so that we walk the epoll tree and ensure that this + * insertion does not create a cycle of epoll file descriptors, which + * could lead to deadlock. We need a global mutex to prevent two + * simultaneous inserts (A into B and B into A) from racing and + * constructing a cycle without either insert observing that it is + * going to. * It is possible to drop the "ep->mtx" and to use the global * mutex "epmutex" (together with "ep->lock") to have it working, * but having "ep->mtx" will make the interface more scalable. @@ -227,6 +234,9 @@ static int max_user_watches __read_mostly; */ static DEFINE_MUTEX(epmutex); +/* Used to check for epoll file descriptor inclusion loops */ +static struct nested_calls poll_loop_ncalls; + /* Used for safe wake up implementation */ static struct nested_calls poll_safewake_ncalls; @@ -1181,6 +1191,62 @@ retry: return res; } +/** + * ep_loop_check_proc - Callback function to be passed to the @ep_call_nested() + * API, to verify that adding an epoll file inside another + * epoll structure, does not violate the constraints, in + * terms of closed loops, or too deep chains (which can + * result in excessive stack usage). + * + * @priv: Pointer to the epoll file to be currently checked. + * @cookie: Original cookie for this call. This is the top-of-the-chain epoll + * data structure pointer. + * @call_nests: Current dept of the @ep_call_nested() call stack. + * + * Returns: Returns zero if adding the epoll @file inside current epoll + * structure @ep does not violate the constraints, or -1 otherwise. + */ +static int ep_loop_check_proc(void *priv, void *cookie, int call_nests) +{ + int error = 0; + struct file *file = priv; + struct eventpoll *ep = file->private_data; + struct rb_node *rbp; + struct epitem *epi; + + mutex_lock(&ep->mtx); + for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) { + epi = rb_entry(rbp, struct epitem, rbn); + if (unlikely(is_file_epoll(epi->ffd.file))) { + error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, + ep_loop_check_proc, epi->ffd.file, + epi->ffd.file->private_data, current); + if (error != 0) + break; + } + } + mutex_unlock(&ep->mtx); + + return error; +} + +/** + * ep_loop_check - Performs a check to verify that adding an epoll file (@file) + * another epoll file (represented by @ep) does not create + * closed loops or too deep chains. + * + * @ep: Pointer to the epoll private data structure. + * @file: Pointer to the epoll file to be checked. + * + * Returns: Returns zero if adding the epoll @file inside current epoll + * structure @ep does not violate the constraints, or -1 otherwise. + */ +static int ep_loop_check(struct eventpoll *ep, struct file *file) +{ + return ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, + ep_loop_check_proc, file, ep, current); +} + /* * Open an eventpoll file descriptor. */ @@ -1229,6 +1295,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event __user *, event) { int error; + int did_lock_epmutex = 0; struct file *file, *tfile; struct eventpoll *ep; struct epitem *epi; @@ -1270,6 +1337,25 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, */ ep = file->private_data; + /* + * When we insert an epoll file descriptor, inside another epoll file + * descriptor, there is the change of creating closed loops, which are + * better be handled here, than in more critical paths. + * + * We hold epmutex across the loop check and the insert in this case, in + * order to prevent two separate inserts from racing and each doing the + * insert "at the same time" such that ep_loop_check passes on both + * before either one does the insert, thereby creating a cycle. + */ + if (unlikely(is_file_epoll(tfile) && op == EPOLL_CTL_ADD)) { + mutex_lock(&epmutex); + did_lock_epmutex = 1; + error = -ELOOP; + if (ep_loop_check(ep, tfile) != 0) + goto error_tgt_fput; + } + + mutex_lock(&ep->mtx); /* @@ -1305,6 +1391,9 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, mutex_unlock(&ep->mtx); error_tgt_fput: + if (unlikely(did_lock_epmutex)) + mutex_unlock(&epmutex); + fput(tfile); error_fput: fput(file); @@ -1423,6 +1512,12 @@ static int __init eventpoll_init(void) max_user_watches = (((si.totalram - si.totalhigh) / 25) << PAGE_SHIFT) / EP_ITEM_COST; + /* + * Initialize the structure used to perform epoll file descriptor + * inclusion loops checks. + */ + ep_nested_calls_init(&poll_loop_ncalls); + /* Initialize the structure used to perform safe poll wait head wake ups */ ep_nested_calls_init(&poll_safewake_ncalls); -- cgit v1.2.3 From e609b7f09120400455b6d54bae2cb56c85578d42 Mon Sep 17 00:00:00 2001 From: Timo Warns Date: Fri, 25 Feb 2011 14:44:21 -0800 Subject: ldm: corrupted partition table can cause kernel oops commit 294f6cf48666825d23c9372ef37631232746e40d upstream. The kernel automatically evaluates partition tables of storage devices. The code for evaluating LDM partitions (in fs/partitions/ldm.c) contains a bug that causes a kernel oops on certain corrupted LDM partitions. A kernel subsystem seems to crash, because, after the oops, the kernel no longer recognizes newly connected storage devices. The patch changes ldm_parse_vmdb() to Validate the value of vblk_size. Signed-off-by: Timo Warns Signed-off-by: Andi Kleen Cc: Eugene Teo Acked-by: Richard Russon Cc: Harvey Harrison Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/partitions/ldm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c index 648c9d8f3357..5638c19a0450 100644 --- a/fs/partitions/ldm.c +++ b/fs/partitions/ldm.c @@ -251,6 +251,11 @@ static bool ldm_parse_vmdb (const u8 *data, struct vmdb *vm) } vm->vblk_size = get_unaligned_be32(data + 0x08); + if (vm->vblk_size == 0) { + ldm_error ("Illegal VBLK size"); + return false; + } + vm->vblk_offset = get_unaligned_be32(data + 0x0C); vm->last_vblk_seq = get_unaligned_be32(data + 0x04); -- cgit v1.2.3 From e918f6a71094520d8a7db5a2c6aa94f3859e7faa Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 16 Feb 2011 13:58:51 +1100 Subject: md: correctly handle probe of an 'mdp' device. commit 8f5f02c460b7ca74ce55ce126ce0c1e58a3f923d upstream. 'mdp' devices are md devices with preallocated device numbers for partitions. As such it is possible to mknod and open a partition before opening the whole device. this causes md_probe() to be called with a device number of a partition, which in-turn calls mddev_find with such a number. However mddev_find expects the number of a 'whole device' and does the wrong thing with partition numbers. So add code to mddev_find to remove the 'partition' part of a device number and just work with the 'whole device'. This patch addresses https://bugzilla.kernel.org/show_bug.cgi?id=28652 Reported-by: hkmaly@bigfoot.com Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/md/md.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index 605166b0ed2f..ff1b20d4cf5f 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -441,6 +441,9 @@ static mddev_t * mddev_find(dev_t unit) { mddev_t *mddev, *new = NULL; + if (unit && MAJOR(unit) != MD_MAJOR) + unit &= ~((1< Date: Thu, 24 Feb 2011 15:53:46 +0100 Subject: x86 quirk: Fix polarity for IRQ0 pin2 override on SB800 systems commit 7f74f8f28a2bd9db9404f7d364e2097a0c42cc12 upstream. On some SB800 systems polarity for IOAPIC pin2 is wrongly specified as low active by BIOS. This caused system hangs after resume from S3 when HPET was used in one-shot mode on such systems because a timer interrupt was missed (HPET signal is high active). For more details see: http://marc.info/?l=linux-kernel&m=129623757413868 Tested-by: Manoj Iyer Tested-by: Andre Przywara Signed-off-by: Andreas Herrmann Signed-off-by: Andi Kleen Cc: Borislav Petkov LKML-Reference: <20110224145346.GD3658@alberich.amd.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/acpi.h | 1 + arch/x86/kernel/acpi/boot.c | 14 ++++++++++---- arch/x86/kernel/early-quirks.c | 16 +++++++--------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index aa2c39d968fc..27d837979e80 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -88,6 +88,7 @@ extern int acpi_disabled; extern int acpi_pci_disabled; extern int acpi_skip_timer_override; extern int acpi_use_timer_override; +extern int acpi_fix_pin2_polarity; extern u8 acpi_sci_flags; extern int acpi_sci_override_gsi; diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index c05872aa3ce0..510bc6db1bd3 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -72,6 +72,7 @@ u8 acpi_sci_flags __initdata; int acpi_sci_override_gsi __initdata; int acpi_skip_timer_override __initdata; int acpi_use_timer_override __initdata; +int acpi_fix_pin2_polarity __initdata; #ifdef CONFIG_X86_LOCAL_APIC static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; @@ -410,10 +411,15 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header, return 0; } - if (acpi_skip_timer_override && - intsrc->source_irq == 0 && intsrc->global_irq == 2) { - printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n"); - return 0; + if (intsrc->source_irq == 0 && intsrc->global_irq == 2) { + if (acpi_skip_timer_override) { + printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n"); + return 0; + } + if (acpi_fix_pin2_polarity && (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) { + intsrc->inti_flags &= ~ACPI_MADT_POLARITY_MASK; + printk(PREFIX "BIOS IRQ0 pin2 override: forcing polarity to high active.\n"); + } } mp_override_legacy_irq(intsrc->source_irq, diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index ebdb85cf2686..ef01d3d6a5a9 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -145,15 +145,10 @@ static void __init ati_bugs(int num, int slot, int func) static u32 __init ati_sbx00_rev(int num, int slot, int func) { - u32 old, d; + u32 d; - d = read_pci_config(num, slot, func, 0x70); - old = d; - d &= ~(1<<8); - write_pci_config(num, slot, func, 0x70, d); d = read_pci_config(num, slot, func, 0x8); d &= 0xff; - write_pci_config(num, slot, func, 0x70, old); return d; } @@ -162,13 +157,16 @@ static void __init ati_bugs_contd(int num, int slot, int func) { u32 d, rev; - if (acpi_use_timer_override) - return; - rev = ati_sbx00_rev(num, slot, func); + if (rev >= 0x40) + acpi_fix_pin2_polarity = 1; + if (rev > 0x13) return; + if (acpi_use_timer_override) + return; + /* check for IRQ0 interrupt swap */ d = read_pci_config(num, slot, func, 0x64); if (!(d & (1<<14))) -- cgit v1.2.3 From f239e2d130e493b80338290722c902f0e6e3198d Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Sat, 12 Feb 2011 14:06:06 -0800 Subject: xhci: Avoid BUG() in interrupt context commit 68e41c5d032668e2905404afbef75bc58be179d6 upstream. Change the BUGs in xhci_find_new_dequeue_state() to WARN_ONs, to avoid bringing down the box if one of them is hit This patch should be queued for stable kernels back to 2.6.31. Signed-off-by: Paul Zimmerman Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/xhci-ring.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 221f99930dc3..3f2670dca04c 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -457,8 +457,11 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, state->new_deq_seg = find_trb_seg(cur_td->start_seg, dev->eps[ep_index].stopped_trb, &state->new_cycle_state); - if (!state->new_deq_seg) - BUG(); + if (!state->new_deq_seg) { + WARN_ON(1); + return; + } + /* Dig out the cycle state saved by the xHC during the stop ep cmd */ xhci_dbg(xhci, "Finding endpoint context\n"); ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index); @@ -469,8 +472,10 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, state->new_deq_seg = find_trb_seg(state->new_deq_seg, state->new_deq_ptr, &state->new_cycle_state); - if (!state->new_deq_seg) - BUG(); + if (!state->new_deq_seg) { + WARN_ON(1); + return; + } trb = &state->new_deq_ptr->generic; if ((trb->field[3] & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK) && -- cgit v1.2.3 From 25d6b22368f95c5ef83f1ee7313d3b66fbf027d3 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Sat, 12 Feb 2011 14:06:44 -0800 Subject: xhci: Clarify some expressions in the TRB math commit a2490187011cc2263117626615a581927d19f1d3 upstream. This makes it easier to spot some problems, which will be fixed by the next patch in the series. Also change dev_dbg to dev_err in check_trb_math(), so any math errors will be visible even when running with debug disabled. Note: This patch changes the expressions containing "((1 << TRB_MAX_BUFF_SHIFT) - 1)" to use the equivalent "(TRB_MAX_BUFF_SIZE - 1)". No change in behavior is intended for those expressions. This patch should be queued for stable kernels back to 2.6.31. Signed-off-by: Paul Zimmerman Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/xhci-ring.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 3f2670dca04c..88ea01bec7ec 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1890,7 +1890,7 @@ static unsigned int count_sg_trbs_needed(struct xhci_hcd *xhci, struct urb *urb) /* Scatter gather list entries may cross 64KB boundaries */ running_total = TRB_MAX_BUFF_SIZE - - (sg_dma_address(sg) & ((1 << TRB_MAX_BUFF_SHIFT) - 1)); + (sg_dma_address(sg) & (TRB_MAX_BUFF_SIZE - 1)); if (running_total != 0) num_trbs++; @@ -1920,11 +1920,11 @@ static unsigned int count_sg_trbs_needed(struct xhci_hcd *xhci, struct urb *urb) static void check_trb_math(struct urb *urb, int num_trbs, int running_total) { if (num_trbs != 0) - dev_dbg(&urb->dev->dev, "%s - ep %#x - Miscalculated number of " + dev_err(&urb->dev->dev, "%s - ep %#x - Miscalculated number of " "TRBs, %d left\n", __func__, urb->ep->desc.bEndpointAddress, num_trbs); if (running_total != urb->transfer_buffer_length) - dev_dbg(&urb->dev->dev, "%s - ep %#x - Miscalculated tx length, " + dev_err(&urb->dev->dev, "%s - ep %#x - Miscalculated tx length, " "queued %#x (%d), asked for %#x (%d)\n", __func__, urb->ep->desc.bEndpointAddress, @@ -2051,8 +2051,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, sg = urb->sg; addr = (u64) sg_dma_address(sg); this_sg_len = sg_dma_len(sg); - trb_buff_len = TRB_MAX_BUFF_SIZE - - (addr & ((1 << TRB_MAX_BUFF_SHIFT) - 1)); + trb_buff_len = TRB_MAX_BUFF_SIZE - (addr & (TRB_MAX_BUFF_SIZE - 1)); trb_buff_len = min_t(int, trb_buff_len, this_sg_len); if (trb_buff_len > urb->transfer_buffer_length) trb_buff_len = urb->transfer_buffer_length; @@ -2088,7 +2087,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, (unsigned int) (addr + TRB_MAX_BUFF_SIZE) & ~(TRB_MAX_BUFF_SIZE - 1), (unsigned int) addr + trb_buff_len); if (TRB_MAX_BUFF_SIZE - - (addr & ((1 << TRB_MAX_BUFF_SHIFT) - 1)) < trb_buff_len) { + (addr & (TRB_MAX_BUFF_SIZE - 1)) < trb_buff_len) { xhci_warn(xhci, "WARN: sg dma xfer crosses 64KB boundaries!\n"); xhci_dbg(xhci, "Next boundary at %#x, end dma = %#x\n", (unsigned int) (addr + TRB_MAX_BUFF_SIZE) & ~(TRB_MAX_BUFF_SIZE - 1), @@ -2132,7 +2131,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, } trb_buff_len = TRB_MAX_BUFF_SIZE - - (addr & ((1 << TRB_MAX_BUFF_SHIFT) - 1)); + (addr & (TRB_MAX_BUFF_SIZE - 1)); trb_buff_len = min_t(int, trb_buff_len, this_sg_len); if (running_total + trb_buff_len > urb->transfer_buffer_length) trb_buff_len = @@ -2171,7 +2170,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, num_trbs = 0; /* How much data is (potentially) left before the 64KB boundary? */ running_total = TRB_MAX_BUFF_SIZE - - (urb->transfer_dma & ((1 << TRB_MAX_BUFF_SHIFT) - 1)); + (urb->transfer_dma & (TRB_MAX_BUFF_SIZE - 1)); /* If there's some data on this 64KB chunk, or we have to send a * zero-length transfer, we need at least one TRB @@ -2211,8 +2210,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /* How much data is in the first TRB? */ addr = (u64) urb->transfer_dma; trb_buff_len = TRB_MAX_BUFF_SIZE - - (urb->transfer_dma & ((1 << TRB_MAX_BUFF_SHIFT) - 1)); - if (urb->transfer_buffer_length < trb_buff_len) + (urb->transfer_dma & (TRB_MAX_BUFF_SIZE - 1)); + if (trb_buff_len > urb->transfer_buffer_length) trb_buff_len = urb->transfer_buffer_length; first_trb = true; -- cgit v1.2.3 From 3f2e65401564db89de1c91901287b483f38db5c6 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Sat, 12 Feb 2011 14:07:20 -0800 Subject: xhci: Fix errors in the running total calculations in the TRB math commit 5807795bd4dececdf553719cc02869e633395787 upstream. Calculations like running_total = TRB_MAX_BUFF_SIZE - (sg_dma_address(sg) & (TRB_MAX_BUFF_SIZE - 1)); if (running_total != 0) num_trbs++; are incorrect, because running_total can never be zero, so the if() expression will never be true. I think the intention was that running_total be in the range of 0 to TRB_MAX_BUFF_SIZE-1, not 1 to TRB_MAX_BUFF_SIZE. So adding a running_total &= TRB_MAX_BUFF_SIZE - 1; fixes the problem. This patch should be queued for stable kernels back to 2.6.31. Signed-off-by: Paul Zimmerman Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/xhci-ring.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 88ea01bec7ec..1801c56c8082 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1891,6 +1891,7 @@ static unsigned int count_sg_trbs_needed(struct xhci_hcd *xhci, struct urb *urb) /* Scatter gather list entries may cross 64KB boundaries */ running_total = TRB_MAX_BUFF_SIZE - (sg_dma_address(sg) & (TRB_MAX_BUFF_SIZE - 1)); + running_total &= TRB_MAX_BUFF_SIZE - 1; if (running_total != 0) num_trbs++; @@ -2171,6 +2172,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /* How much data is (potentially) left before the 64KB boundary? */ running_total = TRB_MAX_BUFF_SIZE - (urb->transfer_dma & (TRB_MAX_BUFF_SIZE - 1)); + running_total &= TRB_MAX_BUFF_SIZE - 1; /* If there's some data on this 64KB chunk, or we have to send a * zero-length transfer, we need at least one TRB -- cgit v1.2.3 From 0fa2aea484fd2fd9a713c77445a1bc49eafd3ad7 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Sat, 12 Feb 2011 14:07:57 -0800 Subject: xhci: Fix an error in count_sg_trbs_needed() commit bcd2fde05341cef0052e49566ec88b406a521cf3 upstream. The expression while (running_total < sg_dma_len(sg)) does not take into account that the remaining data length can be less than sg_dma_len(sg). In that case, running_total can end up being greater than the total data length, so an extra TRB is counted. Changing the expression to while (running_total < sg_dma_len(sg) && running_total < temp) fixes that. This patch should be queued for stable kernels back to 2.6.31. Signed-off-by: Paul Zimmerman Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/xhci-ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 1801c56c8082..4723a400d868 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1896,7 +1896,7 @@ static unsigned int count_sg_trbs_needed(struct xhci_hcd *xhci, struct urb *urb) num_trbs++; /* How many more 64KB chunks to transfer, how many more TRBs? */ - while (running_total < sg_dma_len(sg)) { + while (running_total < sg_dma_len(sg) && running_total < temp) { num_trbs++; running_total += TRB_MAX_BUFF_SIZE; } -- cgit v1.2.3 From 4bb1e0d018b987cbbac02b631242cbecdf4c6ae0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 9 Feb 2011 21:48:36 -0800 Subject: x25: Do not reference freed memory. commit 96642d42f076101ba98866363d908cab706d156c upstream. In x25_link_free(), we destroy 'nb' before dereferencing 'nb->dev'. Don't do this, because 'nb' might be freed by then. Reported-by: Randy Dunlap Tested-by: Randy Dunlap Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/x25/x25_link.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c index b25c6463c3e9..88048b6b0b2b 100644 --- a/net/x25/x25_link.c +++ b/net/x25/x25_link.c @@ -392,9 +392,12 @@ void __exit x25_link_free(void) write_lock_bh(&x25_neigh_list_lock); list_for_each_safe(entry, tmp, &x25_neigh_list) { + struct net_device *dev; + nb = list_entry(entry, struct x25_neigh, node); + dev = nb->dev; __x25_remove_neigh(nb); - dev_put(nb->dev); + dev_put(dev); } write_unlock_bh(&x25_neigh_list_lock); } -- cgit v1.2.3 From 065d36903eda46c9b3434feaebc9b2e2b48c1689 Mon Sep 17 00:00:00 2001 From: Tristan Ye Date: Fri, 21 Jan 2011 18:20:18 +0800 Subject: Ocfs2/refcounttree: Fix a bug for refcounttree to writeback clusters in a right number. commit acf3bb007e5636ef4c17505affb0974175108553 upstream. Current refcounttree codes actually didn't writeback the new pages out in write-back mode, due to a bug of always passing a ZERO number of clusters to 'ocfs2_cow_sync_writeback', the patch tries to pass a proper one in. Signed-off-by: Tristan Ye Signed-off-by: Joel Becker Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ocfs2/refcounttree.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 73a11ccfd4c2..c90b2dd25e0f 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -3215,7 +3215,7 @@ static int ocfs2_make_clusters_writable(struct super_block *sb, u32 num_clusters, unsigned int e_flags) { int ret, delete, index, credits = 0; - u32 new_bit, new_len; + u32 new_bit, new_len, orig_num_clusters; unsigned int set_len; struct ocfs2_super *osb = OCFS2_SB(sb); handle_t *handle; @@ -3248,6 +3248,8 @@ static int ocfs2_make_clusters_writable(struct super_block *sb, goto out; } + orig_num_clusters = num_clusters; + while (num_clusters) { ret = ocfs2_get_refcount_rec(ref_ci, context->ref_root_bh, p_cluster, num_clusters, @@ -3335,7 +3337,8 @@ static int ocfs2_make_clusters_writable(struct super_block *sb, * in write-back mode. */ if (context->get_clusters == ocfs2_di_get_clusters) { - ret = ocfs2_cow_sync_writeback(sb, context, cpos, num_clusters); + ret = ocfs2_cow_sync_writeback(sb, context, cpos, + orig_num_clusters); if (ret) mlog_errno(ret); } -- cgit v1.2.3 From ef7626ef2ce9260ef806b1f21b2340007df790ea Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 24 Feb 2011 08:35:06 +1000 Subject: drm: fix unsigned vs signed comparison issue in modeset ctl ioctl. commit 1922756124ddd53846877416d92ba4a802bc658f upstream. This fixes CVE-2011-1013. Reported-by: Matthiew Herrb (OpenBSD X.org team) Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/drm_irq.c | 3 ++- include/drm/drmP.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index a263b7070fc6..0ddd10995c46 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -545,7 +545,8 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_modeset_ctl *modeset = data; - int crtc, ret = 0; + int ret = 0; + unsigned int crtc; /* If drm_vblank_init() hasn't been called yet, just no-op */ if (!dev->num_crtcs) diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 7c9d28d635b5..3667812ce6e2 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1021,7 +1021,7 @@ struct drm_device { struct pci_controller *hose; #endif struct drm_sg_mem *sg; /**< Scatter gather memory */ - int num_crtcs; /**< Number of CRTCs on this device */ + unsigned int num_crtcs; /**< Number of CRTCs on this device */ void *dev_private; /**< device private data */ void *mm_private; struct address_space *dev_mapping; -- cgit v1.2.3 From dc85a0dd595f342727bdae2ab72b6e860b8c38ab Mon Sep 17 00:00:00 2001 From: Jochen Friedrich Date: Wed, 26 Jan 2011 11:30:01 +0100 Subject: mfd: Fix NULL pointer due to non-initialized ucb1x00-ts absinfo commit 9063f1f15eec35e5fd608879cef8be5728f2d12a upstream. Call input_set_abs_params instead of manually setting absbit only. This fixes this oops: Unable to handle kernel NULL pointer dereference at virtual address 00000024 Internal error: Oops: 41b67017 [#1] CPU: 0 Not tainted (2.6.37 #4) pc : [] lr : [<00000000>] psr: 20000093 sp : c19e5f30 ip : c19e5e6c fp : c19e5f58 r10: 00000000 r9 : c19e4000 r8 : 00000003 r7 : 000001e4 r6 : 00000001 r5 : c1854400 r4 : 00000003 r3 : 00000018 r2 : 00000018 r1 : 00000018 r0 : c185447c Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernel Control: c1b6717f Table: c1b6717f DAC: 00000017 Stack: (0xc19e5f30 to 0xc19e6000) 5f20: 00000003 00000003 c1854400 00000013 5f40: 00000001 000001e4 000001c5 c19e5f80 c19e5f5c c016d5e8 c016cf5c 000001e4 5f60: c1854400 c18b5860 00000000 00000171 000001e4 c19e5fc4 c19e5f84 c01559a4 5f80: c016d584 c18b5868 00000000 c1bb5c40 c0035afc c18b5868 c18b5868 c1a55d54 5fa0: c18b5860 c0155750 00000013 00000000 00000000 00000000 c19e5ff4 c19e5fc8 5fc0: c0050174 c015575c 00000000 c18b5860 00000000 c19e5fd4 c19e5fd4 c1a55d54 5fe0: c00500f0 c003b464 00000000 c19e5ff8 c003b464 c00500fc 04000400 04000400 Backtrace: Function entered at [] from [] Function entered at [] from [] r8:000001e4 r7:00000171 r6:00000000 r5:c18b5860 r4:c1854400 Function entered at [] from [] Function entered at [] from [] r6:c003b464 r5:c00500f0 r4:c1a55d54 Code: e59520fc e1a03286 e0433186 e0822003 (e592000c) >>PC; c016d1fc <===== Trace; c016cf50 Trace; c016d5e8 Trace; c016d578 Trace; c01559a4 Trace; c0155750 Trace; c0050174 Trace; c00500f0 Trace; c003b464 Signed-off-by: Jochen Friedrich Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/mfd/ucb1x00-ts.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c index 000cb414a78a..92b85e28a15e 100644 --- a/drivers/mfd/ucb1x00-ts.c +++ b/drivers/mfd/ucb1x00-ts.c @@ -385,12 +385,18 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev) idev->close = ucb1x00_ts_close; __set_bit(EV_ABS, idev->evbit); - __set_bit(ABS_X, idev->absbit); - __set_bit(ABS_Y, idev->absbit); - __set_bit(ABS_PRESSURE, idev->absbit); input_set_drvdata(idev, ts); + ucb1x00_adc_enable(ts->ucb); + ts->x_res = ucb1x00_ts_read_xres(ts); + ts->y_res = ucb1x00_ts_read_yres(ts); + ucb1x00_adc_disable(ts->ucb); + + input_set_abs_params(idev, ABS_X, 0, ts->x_res, 0, 0); + input_set_abs_params(idev, ABS_Y, 0, ts->y_res, 0, 0); + input_set_abs_params(idev, ABS_PRESSURE, 0, 0, 0, 0); + err = input_register_device(idev); if (err) goto fail; -- cgit v1.2.3 From 71f4fa9d7193a64da840be62cc4de3b7e1c6f43c Mon Sep 17 00:00:00 2001 From: Don Zickus Date: Mon, 7 Feb 2011 23:25:00 -0500 Subject: x86: Use u32 instead of long to set reset vector back to 0 commit 299c56966a72b9109d47c71a6db52097098703dd upstream. A customer of ours, complained that when setting the reset vector back to 0, it trashed other data and hung their box. They noticed when only 4 bytes were set to 0 instead of 8, everything worked correctly. Mathew pointed out: | | We're supposed to be resetting trampoline_phys_low and | trampoline_phys_high here, which are two 16-bit values. | Writing 64 bits is definitely going to overwrite space | that we're not supposed to be touching. | So limit the area modified to u32. Signed-off-by: Don Zickus Acked-by: Matthew Garrett Signed-off-by: Andi Kleen LKML-Reference: <1297139100-424-1-git-send-email-dzickus@redhat.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/smpboot_hooks.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/smpboot_hooks.h b/arch/x86/include/asm/smpboot_hooks.h index 1def60114906..cfdc6c88c9d5 100644 --- a/arch/x86/include/asm/smpboot_hooks.h +++ b/arch/x86/include/asm/smpboot_hooks.h @@ -34,7 +34,7 @@ static inline void smpboot_restore_warm_reset_vector(void) */ CMOS_WRITE(0, 0xf); - *((volatile long *)phys_to_virt(apic->trampoline_phys_low)) = 0; + *((volatile u32 *)phys_to_virt(apic->trampoline_phys_low)) = 0; } static inline void __init smpboot_setup_io_apic(void) -- cgit v1.2.3 From 23d154c71721fd0fa6199851078f32e6bd765664 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 25 Feb 2011 14:44:58 +0100 Subject: fuse: fix hang of single threaded fuseblk filesystem commit 5a18ec176c934ca1bc9dc61580a5e0e90a9b5733 upstream. Single threaded NTFS-3G could get stuck if a delayed RELEASE reply triggered a DESTROY request via path_put(). Fix this by a) making RELEASE requests synchronous, whenever possible, on fuseblk filesystems b) if not possible (triggered by an asynchronous read/write) then do the path_put() in a separate thread with schedule_work(). Reported-by: Oliver Neukum Signed-off-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/fuse/file.c | 52 +++++++++++++++++++++++++++++++++++++++++++++------- fs/fuse/fuse_i.h | 6 +++++- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index f6c333ffa244..9576aed1777c 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -86,18 +86,52 @@ struct fuse_file *fuse_file_get(struct fuse_file *ff) return ff; } +static void fuse_release_async(struct work_struct *work) +{ + struct fuse_req *req; + struct fuse_conn *fc; + struct path path; + + req = container_of(work, struct fuse_req, misc.release.work); + path = req->misc.release.path; + fc = get_fuse_conn(path.dentry->d_inode); + + fuse_put_request(fc, req); + path_put(&path); +} + static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req) { - path_put(&req->misc.release.path); + if (fc->destroy_req) { + /* + * If this is a fuseblk mount, then it's possible that + * releasing the path will result in releasing the + * super block and sending the DESTROY request. If + * the server is single threaded, this would hang. + * For this reason do the path_put() in a separate + * thread. + */ + atomic_inc(&req->count); + INIT_WORK(&req->misc.release.work, fuse_release_async); + schedule_work(&req->misc.release.work); + } else { + path_put(&req->misc.release.path); + } } -static void fuse_file_put(struct fuse_file *ff) +static void fuse_file_put(struct fuse_file *ff, bool sync) { if (atomic_dec_and_test(&ff->count)) { struct fuse_req *req = ff->reserved_req; - req->end = fuse_release_end; - fuse_request_send_background(ff->fc, req); + if (sync) { + fuse_request_send(ff->fc, req); + path_put(&req->misc.release.path); + fuse_put_request(ff->fc, req); + } else { + req->end = fuse_release_end; + fuse_request_send_background(ff->fc, req); + } kfree(ff); } } @@ -219,8 +253,12 @@ void fuse_release_common(struct file *file, int opcode) * Normally this will send the RELEASE request, however if * some asynchronous READ or WRITE requests are outstanding, * the sending will be delayed. + * + * Make the release synchronous if this is a fuseblk mount, + * synchronous RELEASE is allowed (and desirable) in this case + * because the server can be trusted not to screw up. */ - fuse_file_put(ff); + fuse_file_put(ff, ff->fc->destroy_req != NULL); } static int fuse_open(struct inode *inode, struct file *file) @@ -558,7 +596,7 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req) page_cache_release(page); } if (req->ff) - fuse_file_put(req->ff); + fuse_file_put(req->ff, false); } static void fuse_send_readpages(struct fuse_req *req, struct file *file) @@ -1137,7 +1175,7 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf, static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req) { __free_page(req->pages[0]); - fuse_file_put(req->ff); + fuse_file_put(req->ff, false); } static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req) diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 8f309f04064e..6b9a74604ec3 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -21,6 +21,7 @@ #include #include #include +#include /** Max number of pages that can be used in a single read request */ #define FUSE_MAX_PAGES_PER_REQ 32 @@ -257,7 +258,10 @@ struct fuse_req { union { struct fuse_forget_in forget_in; struct { - struct fuse_release_in in; + union { + struct fuse_release_in in; + struct work_struct work; + }; struct path path; } release; struct fuse_init_in init_in; -- cgit v1.2.3 From c3b01b0df34002e981ed6d0b04fe8cecd25d3625 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 25 Feb 2011 22:34:23 +0100 Subject: clockevents: Prevent oneshot mode when broadcast device is periodic commit 3a142a0672b48a853f00af61f184c7341ac9c99d upstream. When the per cpu timer is marked CLOCK_EVT_FEAT_C3STOP, then we only can switch into oneshot mode, when the backup broadcast device supports oneshot mode as well. Otherwise we would try to switch the broadcast device into an unsupported mode unconditionally. This went unnoticed so far as the current available broadcast devices support oneshot mode. Seth unearthed this problem while debugging and working around an hpet related BIOS wreckage. Add the necessary check to tick_is_oneshot_available(). Reported-and-tested-by: Seth Forshee Signed-off-by: Thomas Gleixner Signed-off-by: Andi Kleen LKML-Reference: Signed-off-by: Greg Kroah-Hartman --- kernel/time/tick-broadcast.c | 10 ++++++++++ kernel/time/tick-common.c | 6 +++++- kernel/time/tick-internal.h | 3 +++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index b3bafd5fc66d..2030f62d689e 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -600,4 +600,14 @@ int tick_broadcast_oneshot_active(void) return tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT; } +/* + * Check whether the broadcast device supports oneshot. + */ +bool tick_broadcast_oneshot_available(void) +{ + struct clock_event_device *bc = tick_broadcast_device.evtdev; + + return bc ? bc->features & CLOCK_EVT_FEAT_ONESHOT : false; +} + #endif diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index b6b898d2eeef..61e296ba4392 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -51,7 +51,11 @@ int tick_is_oneshot_available(void) { struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; - return dev && (dev->features & CLOCK_EVT_FEAT_ONESHOT); + if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT)) + return 0; + if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) + return 1; + return tick_broadcast_oneshot_available(); } /* diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index 290eefbc1f60..f65d3a723a64 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h @@ -36,6 +36,7 @@ extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup); extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc); extern int tick_broadcast_oneshot_active(void); extern void tick_check_oneshot_broadcast(int cpu); +bool tick_broadcast_oneshot_available(void); # else /* BROADCAST */ static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { @@ -46,6 +47,7 @@ static inline void tick_broadcast_switch_to_oneshot(void) { } static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { } static inline int tick_broadcast_oneshot_active(void) { return 0; } static inline void tick_check_oneshot_broadcast(int cpu) { } +static inline bool tick_broadcast_oneshot_available(void) { return true; } # endif /* !BROADCAST */ #else /* !ONESHOT */ @@ -76,6 +78,7 @@ static inline int tick_resume_broadcast_oneshot(struct clock_event_device *bc) return 0; } static inline int tick_broadcast_oneshot_active(void) { return 0; } +static inline bool tick_broadcast_oneshot_available(void) { return false; } #endif /* !TICK_ONESHOT */ /* -- cgit v1.2.3 From 7c9c7573f5eb5bf6d95e7b7c81d9a4ac99a55c15 Mon Sep 17 00:00:00 2001 From: Josh Hunt Date: Thu, 24 Feb 2011 11:48:22 +0100 Subject: ext2: Fix link count corruption under heavy link+rename load commit e8a80c6f769dd4622d8b211b398452158ee60c0b upstream. vfs_rename_other() does not lock renamed inode with i_mutex. Thus changing i_nlink in a non-atomic manner (which happens in ext2_rename()) can corrupt it as reported and analyzed by Josh. In fact, there is no good reason to mess with i_nlink of the moved file. We did it presumably to simulate linking into the new directory and unlinking from an old one. But the practical effect of this is disputable because fsck can possibly treat file as being properly linked into both directories without writing any error which is confusing. So we just stop increment-decrement games with i_nlink which also fixes the corruption. CC: Al Viro Signed-off-by: Josh Hunt Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ext2/namei.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index 71efb0e9a3f2..b5d9028af770 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -344,7 +344,6 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry, new_de = ext2_find_entry (new_dir, &new_dentry->d_name, &new_page); if (!new_de) goto out_dir; - inode_inc_link_count(old_inode); ext2_set_link(new_dir, new_de, new_page, old_inode, 1); new_inode->i_ctime = CURRENT_TIME_SEC; if (dir_de) @@ -356,12 +355,9 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry, if (new_dir->i_nlink >= EXT2_LINK_MAX) goto out_dir; } - inode_inc_link_count(old_inode); err = ext2_add_link(new_dentry, old_inode); - if (err) { - inode_dec_link_count(old_inode); + if (err) goto out_dir; - } if (dir_de) inode_inc_link_count(new_dir); } @@ -369,12 +365,11 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry, /* * Like most other Unix systems, set the ctime for inodes on a * rename. - * inode_dec_link_count() will mark the inode dirty. */ old_inode->i_ctime = CURRENT_TIME_SEC; + mark_inode_dirty(old_inode); ext2_delete_entry (old_de, old_page); - inode_dec_link_count(old_inode); if (dir_de) { if (old_dir != new_dir) -- cgit v1.2.3 From 85dbd9451121547d212ccd64af3c79111b901243 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 26 Feb 2011 12:58:06 +0100 Subject: p54usb: add Senao NUB-350 usbid commit 2b799a6b25bb9f9fbc478782cd9503e8066ab618 upstream. Reported-by: Mark Davis Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/p54/p54usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 967a200aabdc..2943f04e109e 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -97,6 +97,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */ {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ {USB_DEVICE(0x1668, 0x1050)}, /* Actiontec 802UIG-1 */ + {USB_DEVICE(0x1740, 0x1000)}, /* Senao NUB-350 */ {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ {USB_DEVICE(0x2001, 0x3705)}, /* D-Link DWL-G120 rev C1 */ {USB_DEVICE(0x413c, 0x5513)}, /* Dell WLA3310 USB Wireless Adapter */ -- cgit v1.2.3 From e64b535e21ce80a24123c0dd4de56eb490faaa81 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 1 Mar 2011 23:02:07 -0800 Subject: dccp: fix oops on Reset after close commit 720dc34bbbe9493c7bd48b2243058b4e447a929d upstream. This fixes a bug in the order of dccp_rcv_state_process() that still permitted reception even after closing the socket. A Reset after close thus causes a NULL pointer dereference by not preventing operations on an already torn-down socket. dccp_v4_do_rcv() | | state other than OPEN v dccp_rcv_state_process() | | DCCP_PKT_RESET v dccp_rcv_reset() | v dccp_time_wait() WARNING: at net/ipv4/inet_timewait_sock.c:141 __inet_twsk_hashdance+0x48/0x128() Modules linked in: arc4 ecb carl9170 rt2870sta(C) mac80211 r8712u(C) crc_ccitt ah [] (unwind_backtrace+0x0/0xec) from [] (warn_slowpath_common) [] (warn_slowpath_common+0x4c/0x64) from [] (warn_slowpath_n) [] (warn_slowpath_null+0x1c/0x24) from [] (__inet_twsk_hashd) [] (__inet_twsk_hashdance+0x48/0x128) from [] (dccp_time_wai) [] (dccp_time_wait+0x40/0xc8) from [] (dccp_rcv_state_proces) [] (dccp_rcv_state_process+0x120/0x538) from [] (dccp_v4_do_) [] (dccp_v4_do_rcv+0x11c/0x14c) from [] (release_sock+0xac/0) [] (release_sock+0xac/0x110) from [] (dccp_close+0x28c/0x380) [] (dccp_close+0x28c/0x380) from [] (inet_release+0x64/0x70) The fix is by testing the socket state first. Receiving a packet in Closed state now also produces the required "No connection" Reset reply of RFC 4340, 8.3.1. Reported-and-tested-by: Johan Hovold Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/dccp/input.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/dccp/input.c b/net/dccp/input.c index 6beb6a7d6fba..ca168692f170 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -617,6 +617,9 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, /* Caller (dccp_v4_do_rcv) will send Reset */ dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; return 1; + } else if (sk->sk_state == DCCP_CLOSED) { + dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; + return 1; } if (sk->sk_state != DCCP_REQUESTING && sk->sk_state != DCCP_RESPOND) { @@ -679,10 +682,6 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, } switch (sk->sk_state) { - case DCCP_CLOSED: - dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; - return 1; - case DCCP_REQUESTING: queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len); if (queued >= 0) -- cgit v1.2.3 From e75a325f093d5e85b246f69cb3139e684d1023ab Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 2 Feb 2011 09:30:36 +0000 Subject: e1000e: disable broken PHY wakeup for ICH10 LOMs, use MAC wakeup instead commit 4def99bbfd46e05c5e03b5b282cb4ee30e27ff19 upstream. When support for 82577/82578 was added[1] in 2.6.31, PHY wakeup was in- advertently enabled (even though it does not function properly) on ICH10 LOMs. This patch makes it so that the ICH10 LOMs use MAC wakeup instead as was done with the initial support for those devices (i.e. 82567LM-3, 82567LF-3 and 82567V-4). [1] commit a4f58f5455ba0efda36fb33c37074922d1527a10 Reported-by: Aurelien Jarno Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/e1000e/netdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index ba246793ea4a..513a4b8e89c4 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -5678,7 +5678,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev, /* APME bit in EEPROM is mapped to WUC.APME */ eeprom_data = er32(WUC); eeprom_apme_mask = E1000_WUC_APME; - if (eeprom_data & E1000_WUC_PHY_WAKE) + if ((hw->mac.type > e1000_ich10lan) && + (eeprom_data & E1000_WUC_PHY_WAKE)) adapter->flags2 |= FLAG2_HAS_PHY_WAKEUP; } else if (adapter->flags & FLAG_APME_IN_CTRL3) { if (adapter->flags & FLAG_APME_CHECK_PORT_B && -- cgit v1.2.3 From 91cda1a87e73670380948ad0954a2b544adf88fc Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 22 Feb 2011 02:00:11 +0000 Subject: r8169: disable ASPM commit ba04c7c93bbcb48ce880cf75b6e9dffcd79d4c7b upstream. For some time is known that ASPM is causing troubles on r8169, i.e. make device randomly stop working without any errors in dmesg. Currently Tomi Leppikangas reports that system with r8169 device hangs with MCE errors when ASPM is enabled: https://bugzilla.redhat.com/show_bug.cgi?id=642861#c4 Lets disable ASPM for r8169 devices at all, to avoid problems with r8169 PCIe devices at least for some users. Reported-by: Tomi Leppikangas Signed-off-by: Stanislaw Gruszka Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/r8169.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 857ecafefd2c..003923adec72 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -3040,6 +3041,11 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) mii->reg_num_mask = 0x1f; mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); + /* disable ASPM completely as that cause random device stop working + * problems as well as full system hangs for some PCIe devices users */ + pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | + PCIE_LINK_STATE_CLKPM); + /* enable device (incl. PCI PM wakeup and hotplug setup) */ rc = pci_enable_device(pdev); if (rc < 0) { -- cgit v1.2.3 From 7e150642300a8c69f3e219f960f0d454ca442df8 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 11 Oct 2010 11:28:16 -0700 Subject: usb: iowarrior: don't trust report_size for buffer size commit 3ed780117dbe5acb64280d218f0347f238dafed0 upstream. If the iowarrior devices in this case statement support more than 8 bytes per report, it is possible to write past the end of a kernel heap allocation. This will probably never be possible, but change the allocation to be more defensive anyway. Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman Acked-by: Brandon Philips Signed-off-by: Andi Kleen --- drivers/usb/misc/iowarrior.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index b47e694207a3..654243e0c9c0 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -373,7 +373,7 @@ static ssize_t iowarrior_write(struct file *file, case USB_DEVICE_ID_CODEMERCS_IOWPV2: case USB_DEVICE_ID_CODEMERCS_IOW40: /* IOW24 and IOW40 use a synchronous call */ - buf = kmalloc(8, GFP_KERNEL); /* 8 bytes are enough for both products */ + buf = kmalloc(count, GFP_KERNEL); if (!buf) { retval = -ENOMEM; goto exit; -- cgit v1.2.3 From 23816cabbcac4826dd62590edeb0518e318217a7 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 11 Feb 2011 07:44:16 +0000 Subject: arp_notify: unconditionally send gratuitous ARP for NETDEV_NOTIFY_PEERS. commit d11327ad6695db8117c78d70611e71102ceec2ac upstream. NETDEV_NOTIFY_PEER is an explicit request by the driver to send a link notification while NETDEV_UP/NETDEV_CHANGEADDR generate link notifications as a sort of side effect. In the later cases the sysctl option is present because link notification events can have undesired effects e.g. if the link is flapping. I don't think this applies in the case of an explicit request from a driver. This patch makes NETDEV_NOTIFY_PEER unconditional, if preferred we could add a new sysctl for this case which defaults to on. This change causes Xen post-migration ARP notifications (which cause switches to relearn their MAC tables etc) to be sent by default. Signed-off-by: Ian Campbell Signed-off-by: David S. Miller Signed-off-by: Andi Kleen [reported to solve hyperv live migration problem - gkh] Cc: Haiyang Zhang Cc: Mike Surcouf Cc: Hank Janssen Signed-off-by: Greg Kroah-Hartman --- net/ipv4/devinet.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index da14c49284f4..ff6c372e95b1 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1029,6 +1029,21 @@ static inline bool inetdev_valid_mtu(unsigned mtu) return mtu >= 68; } +static void inetdev_send_gratuitous_arp(struct net_device *dev, + struct in_device *in_dev) + +{ + struct in_ifaddr *ifa = in_dev->ifa_list; + + if (!ifa) + return; + + arp_send(ARPOP_REQUEST, ETH_P_ARP, + ifa->ifa_address, dev, + ifa->ifa_address, NULL, + dev->dev_addr, NULL); +} + /* Called only under RTNL semaphore */ static int inetdev_event(struct notifier_block *this, unsigned long event, @@ -1081,18 +1096,13 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, } ip_mc_up(in_dev); /* fall through */ - case NETDEV_NOTIFY_PEERS: case NETDEV_CHANGEADDR: + if (!IN_DEV_ARP_NOTIFY(in_dev)) + break; + /* fall through */ + case NETDEV_NOTIFY_PEERS: /* Send gratuitous ARP to notify of link change */ - if (IN_DEV_ARP_NOTIFY(in_dev)) { - struct in_ifaddr *ifa = in_dev->ifa_list; - - if (ifa) - arp_send(ARPOP_REQUEST, ETH_P_ARP, - ifa->ifa_address, dev, - ifa->ifa_address, NULL, - dev->dev_addr, NULL); - } + inetdev_send_gratuitous_arp(dev, in_dev); break; case NETDEV_DOWN: ip_mc_down(in_dev); -- cgit v1.2.3 From d63d8586fd2d38b7faa03938f7a9957f4f021427 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Mon, 17 Jan 2011 20:15:44 +0300 Subject: CIFS: Fix oplock break handling (try #2) commit 12fed00de963433128b5366a21a55808fab2f756 upstream. When we get oplock break notification we should set the appropriate value of OplockLevel field in oplock break acknowledge according to the oplock level held by the client in this time. As we only can have level II oplock or no oplock in the case of oplock break, we should be aware only about clientCanCacheRead field in cifsInodeInfo structure. Signed-off-by: Pavel Shilovsky Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/cifs/cifsproto.h | 2 +- fs/cifs/cifssmb.c | 4 +++- fs/cifs/file.c | 21 +++++++++++---------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 4c54a8b3da5b..21088dc9f66f 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -343,7 +343,7 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, const __u16 netfid, const __u64 len, const __u64 offset, const __u32 numUnlock, const __u32 numLock, const __u8 lockType, - const bool waitFlag); + const bool waitFlag, const __u8 oplock_level); extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, const __u16 smb_file_id, const int get_flag, const __u64 len, struct file_lock *, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index c65c3419dd37..6b764d7505de 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1647,7 +1647,8 @@ int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, const __u16 smb_file_id, const __u64 len, const __u64 offset, const __u32 numUnlock, - const __u32 numLock, const __u8 lockType, const bool waitFlag) + const __u32 numLock, const __u8 lockType, + const bool waitFlag, const __u8 oplock_level) { int rc = 0; LOCK_REQ *pSMB = NULL; @@ -1675,6 +1676,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, pSMB->NumberOfLocks = cpu_to_le16(numLock); pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock); pSMB->LockType = lockType; + pSMB->OplockLevel = oplock_level; pSMB->AndXCommand = 0xFF; /* none */ pSMB->Fid = smb_file_id; /* netfid stays le */ diff --git a/fs/cifs/file.c b/fs/cifs/file.c index de2e6c42e243..8a9e6888c041 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -796,12 +796,12 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) /* BB we could chain these into one lock request BB */ rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start, - 0, 1, lockType, 0 /* wait flag */ ); + 0, 1, lockType, 0 /* wait flag */, 0); if (rc == 0) { rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start, 1 /* numUnlock */ , 0 /* numLock */ , lockType, - 0 /* wait flag */ ); + 0 /* wait flag */, 0); pfLock->fl_type = F_UNLCK; if (rc != 0) cERROR(1, "Error unlocking previously locked " @@ -818,13 +818,13 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start, 0, 1, lockType | LOCKING_ANDX_SHARED_LOCK, - 0 /* wait flag */); + 0 /* wait flag */, 0); if (rc == 0) { rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start, 1, 0, lockType | LOCKING_ANDX_SHARED_LOCK, - 0 /* wait flag */); + 0 /* wait flag */, 0); pfLock->fl_type = F_RDLCK; if (rc != 0) cERROR(1, "Error unlocking " @@ -868,8 +868,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) if (numLock) { rc = CIFSSMBLock(xid, tcon, netfid, length, - pfLock->fl_start, - 0, numLock, lockType, wait_flag); + pfLock->fl_start, 0, numLock, lockType, + wait_flag, 0); if (rc == 0) { /* For Windows locks we must store them. */ @@ -889,9 +889,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) (pfLock->fl_start + length) >= (li->offset + li->length)) { stored_rc = CIFSSMBLock(xid, tcon, - netfid, - li->length, li->offset, - 1, 0, li->type, false); + netfid, li->length, + li->offset, 1, 0, + li->type, false, 0); if (stored_rc) rc = stored_rc; else { @@ -2300,7 +2300,8 @@ cifs_oplock_break(struct slow_work *work) */ if (!cfile->closePend && !cfile->oplock_break_cancelled) { rc = CIFSSMBLock(0, cifs_sb->tcon, cfile->netfid, 0, 0, 0, 0, - LOCKING_ANDX_OPLOCK_RELEASE, false); + LOCKING_ANDX_OPLOCK_RELEASE, false, + cinode->clientCanCacheRead ? 1 : 0); cFYI(1, "Oplock release rc = %d", rc); } } -- cgit v1.2.3 From ed0afb9880641cc6a22a46b75fcaca67728ce41b Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Fri, 4 Mar 2011 17:36:21 -0800 Subject: cpuset: add a missing unlock in cpuset_write_resmask() commit b75f38d659e6fc747eda64cb72f3920e29dd44a4 upstream. Don't forget to release cgroup_mutex if alloc_trial_cpuset() fails. [akpm@linux-foundation.org: avoid multiple return points] Signed-off-by: Li Zefan Signed-off-by: Andi Kleen Cc: Paul Menage Acked-by: David Rientjes Cc: Miao Xie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/cpuset.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 02b9611eadde..8c781d59f2e6 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -1576,8 +1576,10 @@ static int cpuset_write_resmask(struct cgroup *cgrp, struct cftype *cft, return -ENODEV; trialcs = alloc_trial_cpuset(cs); - if (!trialcs) - return -ENOMEM; + if (!trialcs) { + retval = -ENOMEM; + goto out; + } switch (cft->private) { case FILE_CPULIST: @@ -1592,6 +1594,7 @@ static int cpuset_write_resmask(struct cgroup *cgrp, struct cftype *cft, } free_trial_cpuset(trialcs); +out: cgroup_unlock(); return retval; } -- cgit v1.2.3 From 4e6c91302a8e7073d69adca8100a1f7361050f6f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 3 Mar 2011 17:56:06 +0100 Subject: keyboard: integer underflow bug commit b652277b09d3d030cb074cc6a98ba80b34244c03 upstream. The "ct" variable should be an unsigned int. Both struct kbdiacrs ->kb_cnt and struct kbd_data ->accent_table_size are unsigned ints. Making it signed causes a problem in KBDIACRUC because the user could set the signed bit and cause a buffer overflow. Signed-off-by: Dan Carpenter Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/s390/char/keyboard.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index 18d9a497863b..9b93e4a7261f 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c @@ -460,7 +460,8 @@ kbd_ioctl(struct kbd_data *kbd, struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp; - int ct, perm; + unsigned int ct; + int perm; argp = (void __user *)arg; -- cgit v1.2.3 From d97f1cbed8f5b7aaf11a51d7bd5e4674f3d822c4 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 28 Feb 2011 03:27:53 +0000 Subject: RxRPC: Fix v1 keys commit f009918a1c1bbf8607b8aab3959876913a30193a upstream. commit 339412841d7 (RxRPC: Allow key payloads to be passed in XDR form) broke klog for me. I notice the v1 key struct had a kif_version field added: -struct rxkad_key { - u16 security_index; /* RxRPC header security index */ - u16 ticket_len; /* length of ticket[] */ - u32 expiry; /* time at which expires */ - u32 kvno; /* key version number */ - u8 session_key[8]; /* DES session key */ - u8 ticket[0]; /* the encrypted ticket */ -}; +struct rxrpc_key_data_v1 { + u32 kif_version; /* 1 */ + u16 security_index; + u16 ticket_length; + u32 expiry; /* time_t */ + u32 kvno; + u8 session_key[8]; + u8 ticket[0]; +}; However the code in rxrpc_instantiate strips it away: data += sizeof(kver); datalen -= sizeof(kver); Removing kif_version fixes my problem. Signed-off-by: Anton Blanchard Signed-off-by: David Howells Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/keys/rxrpc-type.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/keys/rxrpc-type.h b/include/keys/rxrpc-type.h index 5cb86c307f5d..fc4875433817 100644 --- a/include/keys/rxrpc-type.h +++ b/include/keys/rxrpc-type.h @@ -99,7 +99,6 @@ struct rxrpc_key_token { * structure of raw payloads passed to add_key() or instantiate key */ struct rxrpc_key_data_v1 { - u32 kif_version; /* 1 */ u16 security_index; u16 ticket_length; u32 expiry; /* time_t */ -- cgit v1.2.3 From 7978eb8d9cf53e9781bc9e143addeee8ee1ec4fe Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Tue, 18 Jan 2011 22:53:47 +0000 Subject: ixgbe: fix for 82599 erratum on Header Splitting commit a124339ad28389093ed15eca990d39c51c5736cc upstream. We have found a hardware erratum on 82599 hardware that can lead to unpredictable behavior when Header Splitting mode is enabled. So we are no longer enabling this feature on affected hardware. Please see the 82599 Specification Update for more information. Signed-off-by: Don Skidmore Tested-by: Stephen Ko Signed-off-by: Jeff Kirsher Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/ixgbe/ixgbe_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 649c8678d343..778243720649 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2658,6 +2658,10 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) if (!adapter->num_vfs) adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED; + /* Disable packet split due to 82599 erratum #45 */ + if (hw->mac.type == ixgbe_mac_82599EB) + adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED; + /* Set the RX buffer length according to the mode */ if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { rx_buf_len = IXGBE_RX_HDR_SIZE; -- cgit v1.2.3 From 551d7fec8a6edde9c3284e26f4566f1453490665 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 23 Feb 2011 21:39:49 -0800 Subject: mm: fix possible cause of a page_mapped BUG commit a3e8cc643d22d2c8ed36b9be7d9c9ca21efcf7f7 upstream. Robert Swiecki reported a BUG_ON(page_mapped) from a fuzzer, punching a hole with madvise(,, MADV_REMOVE). That path is under mutex, and cannot be explained by lack of serialization in unmap_mapping_range(). Reviewing the code, I found one place where vm_truncate_count handling should have been updated, when I switched at the last minute from one way of managing the restart_addr to another: mremap move changes the virtual addresses, so it ought to adjust the restart_addr. But rather than exporting the notion of restart_addr from memory.c, or converting to restart_pgoff throughout, simply reset vm_truncate_count to 0 to force a rescan if mremap move races with preempted truncation. We have no confirmation that this fixes Robert's BUG, but it is a fix that's worth making anyway. Signed-off-by: Hugh Dickins Signed-off-by: Linus Torvalds Signed-off-by: Andi Kleen Cc: Kerin Millar Signed-off-by: Greg Kroah-Hartman --- mm/mremap.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mm/mremap.c b/mm/mremap.c index cde56ee51ef7..10d5f6264514 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -91,9 +91,7 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd, */ mapping = vma->vm_file->f_mapping; spin_lock(&mapping->i_mmap_lock); - if (new_vma->vm_truncate_count && - new_vma->vm_truncate_count != vma->vm_truncate_count) - new_vma->vm_truncate_count = 0; + new_vma->vm_truncate_count = 0; } /* -- cgit v1.2.3 From 125124738e4704bf30ac47a59c96f7e3cbfb8161 Mon Sep 17 00:00:00 2001 From: Matt Evans Date: Mon, 7 Mar 2011 17:26:04 +0530 Subject: powerpc/kexec: Fix orphaned offline CPUs across kexec Commit: e8e5c2155b0035b6e04f29be67f6444bc914005b upstream When CPU hotplug is used, some CPUs may be offline at the time a kexec is performed. The subsequent kernel may expect these CPUs to be already running, and will declare them stuck. On pseries, there's also a soft-offline (cede) state that CPUs may be in; this can also cause problems as the kexeced kernel may ask RTAS if they're online -- and RTAS would say they are. The CPU will either appear stuck, or will cause a crash as we replace its cede loop beneath it. This patch kicks each present offline CPU awake before the kexec, so that none are forever lost to these assumptions in the subsequent kernel. Now, the behaviour is that all available CPUs that were offlined are now online & usable after the kexec. This mimics the behaviour of a full reboot (on which all CPUs will be restarted). Signed-off-by: Matt Evans Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Kamalesh babulal Signed-off-by: Andi Kleen cc: Anton Blanchard Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/machine_kexec_64.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index ed31a29c4ff7..060c6d387569 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -199,9 +200,32 @@ static void kexec_prepare_cpus_wait(int wait_state) mb(); } -static void kexec_prepare_cpus(void) +/* + * We need to make sure each present CPU is online. The next kernel will scan + * the device tree and assume primary threads are online and query secondary + * threads via RTAS to online them if required. If we don't online primary + * threads, they will be stuck. However, we also online secondary threads as we + * may be using 'cede offline'. In this case RTAS doesn't see the secondary + * threads as offline -- and again, these CPUs will be stuck. + * + * So, we online all CPUs that should be running, including secondary threads. + */ +static void wake_offline_cpus(void) { + int cpu = 0; + + for_each_present_cpu(cpu) { + if (!cpu_online(cpu)) { + printk(KERN_INFO "kexec: Waking offline cpu %d.\n", + cpu); + cpu_up(cpu); + } + } +} +static void kexec_prepare_cpus(void) +{ + wake_offline_cpus(); smp_call_function(kexec_smp_down, NULL, /* wait */0); local_irq_disable(); mb(); /* make sure IRQs are disabled before we say they are */ -- cgit v1.2.3 From 3015340ba8ece69d4f3a46319282887b1115913b Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 2 Mar 2011 12:10:13 +0100 Subject: netfilter: nf_log: avoid oops in (un)bind with invalid nfproto values commit 9ef0298a8e5730d9a46d640014c727f3b4152870 upstream. Like many other places, we have to check that the array index is within allowed limits, or otherwise, a kernel oops and other nastiness can ensue when we access memory beyond the end of the array. [ 5954.115381] BUG: unable to handle kernel paging request at 0000004000000000 [ 5954.120014] IP: __find_logger+0x6f/0xa0 [ 5954.123979] nf_log_bind_pf+0x2b/0x70 [ 5954.123979] nfulnl_recv_config+0xc0/0x4a0 [nfnetlink_log] [ 5954.123979] nfnetlink_rcv_msg+0x12c/0x1b0 [nfnetlink] ... The problem goes back to v2.6.30-rc1~1372~1342~31 where nf_log_bind was decoupled from nf_log_register. Reported-by: Miguel Di Ciurcio Filho , via irc.freenode.net/#netfilter Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/netfilter/nf_log.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 7df37fd786bc..2a2a20e24468 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -85,6 +85,8 @@ EXPORT_SYMBOL(nf_log_unregister); int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger) { + if (pf >= ARRAY_SIZE(nf_loggers)) + return -EINVAL; mutex_lock(&nf_log_mutex); if (__find_logger(pf, logger->name) == NULL) { mutex_unlock(&nf_log_mutex); @@ -98,6 +100,8 @@ EXPORT_SYMBOL(nf_log_bind_pf); void nf_log_unbind_pf(u_int8_t pf) { + if (pf >= ARRAY_SIZE(nf_loggers)) + return; mutex_lock(&nf_log_mutex); rcu_assign_pointer(nf_loggers[pf], NULL); mutex_unlock(&nf_log_mutex); -- cgit v1.2.3 From f59cc338d129dfd372658899c9a91287f49b1cb9 Mon Sep 17 00:00:00 2001 From: roel Date: Tue, 8 Mar 2011 22:32:26 +0100 Subject: nfsd: wrong index used in inner loop commit 3ec07aa9522e3d5e9d5ede7bef946756e623a0a0 upstream. [AK plus merged with commit 5a02ab7c3c4580f94d13c683721039855b67cda6 upstream ] Index i was already used in the outer loop Signed-off-by: Roel Kluin Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfsd/nfs4xdr.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 93ff828c22cc..d88539d93caf 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1180,8 +1180,6 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp, READ_BUF(4); READ32(dummy); READ_BUF(dummy * 4); - for (i = 0; i < dummy; ++i) - READ32(dummy); break; case RPC_AUTH_GSS: dprintk("RPC_AUTH_GSS callback secflavor " @@ -1197,7 +1195,6 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp, READ_BUF(4); READ32(dummy); READ_BUF(dummy); - p += XDR_QUADLEN(dummy); break; default: dprintk("Illegal callback secflavor\n"); -- cgit v1.2.3 From 87f18d37dbbfeaf1cb3d8f7de81e38bc849f0536 Mon Sep 17 00:00:00 2001 From: Ivan Vecera Date: Thu, 27 Jan 2011 12:24:11 +0100 Subject: r8169: use RxFIFO overflow workaround for 8168c chipset. commit b5ba6d12bdac21bc0620a5089e0f24e362645efd upstream. I found that one of the 8168c chipsets (concretely XID 1c4000c0) starts generating RxFIFO overflow errors. The result is an infinite loop in interrupt handler as the RxFIFOOver is handled only for ...MAC_VER_11. With the workaround everything goes fine. Signed-off-by: Ivan Vecera Acked-by: Francois Romieu Signed-off-by: Andi Kleen Cc: Hayes Signed-off-by: Greg Kroah-Hartman --- drivers/net/r8169.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 003923adec72..48ed37544792 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -3750,7 +3750,8 @@ static void rtl_hw_start_8168(struct net_device *dev) RTL_W16(IntrMitigate, 0x5151); /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { + if (tp->mac_version == RTL_GIGA_MAC_VER_11 || + tp->mac_version == RTL_GIGA_MAC_VER_22) { tp->intr_event |= RxFIFOOver | PCSTimeout; tp->intr_event &= ~RxOverflow; } @@ -4637,7 +4638,8 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) /* Work around for rx fifo overflow */ if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { + (tp->mac_version == RTL_GIGA_MAC_VER_11 || + tp->mac_version == RTL_GIGA_MAC_VER_22)) { netif_stop_queue(dev); rtl8169_tx_timeout(dev); break; -- cgit v1.2.3 From 764504f33c9f5d2692dac5873c2bbbc7363b525c Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Wed, 2 Mar 2011 00:33:13 +0300 Subject: net: don't allow CAP_NET_ADMIN to load non-netdev kernel modules commit 8909c9ad8ff03611c9c96c9a92656213e4bb495b upstream. Since a8f80e8ff94ecba629542d9b4b5f5a8ee3eb565c any process with CAP_NET_ADMIN may load any module from /lib/modules/. This doesn't mean that CAP_NET_ADMIN is a superset of CAP_SYS_MODULE as modules are limited to /lib/modules/**. However, CAP_NET_ADMIN capability shouldn't allow anybody load any module not related to networking. This patch restricts an ability of autoloading modules to netdev modules with explicit aliases. This fixes CVE-2011-1019. Arnd Bergmann suggested to leave untouched the old pre-v2.6.32 behavior of loading netdev modules by name (without any prefix) for processes with CAP_SYS_MODULE to maintain the compatibility with network scripts that use autoloading netdev modules by aliases like "eth0", "wlan0". Currently there are only three users of the feature in the upstream kernel: ipip, ip_gre and sit. root@albatros:~# capsh --drop=$(seq -s, 0 11),$(seq -s, 13 34) -- root@albatros:~# grep Cap /proc/$$/status CapInh: 0000000000000000 CapPrm: fffffff800001000 CapEff: fffffff800001000 CapBnd: fffffff800001000 root@albatros:~# modprobe xfs FATAL: Error inserting xfs (/lib/modules/2.6.38-rc6-00001-g2bf4ca3/kernel/fs/xfs/xfs.ko): Operation not permitted root@albatros:~# lsmod | grep xfs root@albatros:~# ifconfig xfs xfs: error fetching interface information: Device not found root@albatros:~# lsmod | grep xfs root@albatros:~# lsmod | grep sit root@albatros:~# ifconfig sit sit: error fetching interface information: Device not found root@albatros:~# lsmod | grep sit root@albatros:~# ifconfig sit0 sit0 Link encap:IPv6-in-IPv4 NOARP MTU:1480 Metric:1 root@albatros:~# lsmod | grep sit sit 10457 0 tunnel4 2957 1 sit For CAP_SYS_MODULE module loading is still relaxed: root@albatros:~# grep Cap /proc/$$/status CapInh: 0000000000000000 CapPrm: ffffffffffffffff CapEff: ffffffffffffffff CapBnd: ffffffffffffffff root@albatros:~# ifconfig xfs xfs: error fetching interface information: Device not found root@albatros:~# lsmod | grep xfs xfs 745319 0 Reference: https://lkml.org/lkml/2011/2/24/203 Signed-off-by: Vasiliy Kulikov Signed-off-by: Michael Tokarev Acked-by: David S. Miller Acked-by: Kees Cook Signed-off-by: James Morris Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/linux/netdevice.h | 4 ++++ net/core/dev.c | 13 ++++++++++--- net/ipv4/ip_gre.c | 1 + net/ipv4/ipip.c | 1 + net/ipv6/sit.c | 2 +- 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 142bf182caa8..e857c9455934 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2344,6 +2344,10 @@ do { \ }) #endif +#define MODULE_ALIAS_NETDEV(device) \ + MODULE_ALIAS("netdev-" device) + + #endif /* __KERNEL__ */ #endif /* _LINUX_NETDEVICE_H */ diff --git a/net/core/dev.c b/net/core/dev.c index d7d352ba56cd..7c3e7c36c0b7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1121,13 +1121,20 @@ EXPORT_SYMBOL(netdev_bonding_change); void dev_load(struct net *net, const char *name) { struct net_device *dev; + int no_module; rcu_read_lock(); dev = dev_get_by_name_rcu(net, name); rcu_read_unlock(); - - if (!dev && capable(CAP_NET_ADMIN)) - request_module("%s", name); + no_module = !dev; + if (no_module && capable(CAP_NET_ADMIN)) + no_module = request_module("netdev-%s", name); + if (no_module && capable(CAP_SYS_MODULE)) { + if (!request_module("%s", name)) + pr_err("Loading kernel module for a network device " +"with CAP_SYS_MODULE (deprecated). Use CAP_NET_ADMIN and alias netdev-%s " +"instead\n", name); + } } EXPORT_SYMBOL(dev_load); diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 32618e11076d..cd527c440708 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1701,3 +1701,4 @@ module_exit(ipgre_fini); MODULE_LICENSE("GPL"); MODULE_ALIAS_RTNL_LINK("gre"); MODULE_ALIAS_RTNL_LINK("gretap"); +MODULE_ALIAS_NETDEV("gre0"); diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 7fd636711037..5d8e362b2383 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -850,3 +850,4 @@ static void __exit ipip_fini(void) module_init(ipip_init); module_exit(ipip_fini); MODULE_LICENSE("GPL"); +MODULE_ALIAS_NETDEV("tunl0"); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index e51e650ea80b..2020bea68952 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -1239,4 +1239,4 @@ static int __init sit_init(void) module_init(sit_init); module_exit(sit_cleanup); MODULE_LICENSE("GPL"); -MODULE_ALIAS("sit0"); +MODULE_ALIAS_NETDEV("sit0"); -- cgit v1.2.3 From 9afaa41ad6235dc13c19affd061dffb55cf9c6b2 Mon Sep 17 00:00:00 2001 From: "[Dstephen hemminger" Date: Thu, 31 Mar 2011 11:58:35 -0700 Subject: ip6ip6-autoload-ip6-tunnel Fromm foo From: stephen hemminger Date: Thu, 10 Mar 2011 11:43:19 +0000 (+0000) Subject: ip6ip6: autoload ip6 tunnel From: stephen hemminger commit 6dfbd87a20a737641ef228230c77f4262434fa24 upstream ip6ip6: autoload ip6 tunnel Add necessary alias to autoload ip6ip6 tunnel module. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ipv6/ip6_tunnel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 8f39893d8081..81b78878d5e6 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -57,6 +57,7 @@ MODULE_AUTHOR("Ville Nuorvala"); MODULE_DESCRIPTION("IPv6 tunneling device"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_NETDEV("ip6tnl0"); #define IPV6_TLV_TEL_DST_SIZE 8 -- cgit v1.2.3 From c4fb5a6409c69eeaab515d2f96ed3ba27fee10d8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 13 Mar 2011 13:50:33 +0100 Subject: hwmon/f71882fg: Set platform drvdata to NULL later commit d9ebaa45472c92704f4814682eec21455edcfa1f upstream. This avoids a possible race leading to trying to dereference NULL. Signed-off-by: Hans de Goede Acked-by: Jean Delvare Signed-off-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/hwmon/f71882fg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 537841ef44b9..fec078de1568 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -2100,7 +2100,6 @@ static int f71882fg_remove(struct platform_device *pdev) int nr_fans = (data->type == f71882fg) ? 4 : 3; u8 start_reg = f71882fg_read8(data, F71882FG_REG_START); - platform_set_drvdata(pdev, NULL); if (data->hwmon_dev) hwmon_device_unregister(data->hwmon_dev); @@ -2167,6 +2166,7 @@ static int f71882fg_remove(struct platform_device *pdev) } } + platform_set_drvdata(pdev, NULL); kfree(data); return 0; -- cgit v1.2.3 From a2ee4c35474fb4c5151e0c691540b375fe5f97cf Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 7 Mar 2011 11:04:24 +0800 Subject: mtd: add "platform:" prefix for platform modalias commit c804c733846572ca85c2bba60c7fe6fa024dff18 upstream. Since 43cc71eed1250755986da4c0f9898f9a635cb3bf (platform: prefix MODALIAS with "platform:"), the platform modalias is prefixed with "platform:". Signed-off-by: Axel Lin Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/mtd/nand/omap2.c | 2 +- drivers/mtd/onenand/generic.c | 2 +- drivers/mtd/onenand/omap2.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index ee87325c7712..f613eb250fa4 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1077,6 +1077,6 @@ static void __exit omap_nand_exit(void) module_init(omap_nand_init); module_exit(omap_nand_exit); -MODULE_ALIAS(DRIVER_NAME); +MODULE_ALIAS("platform:" DRIVER_NAME); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Glue layer for NAND flash on TI OMAP boards"); diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c index e78914938c5c..ac08750748a3 100644 --- a/drivers/mtd/onenand/generic.c +++ b/drivers/mtd/onenand/generic.c @@ -131,7 +131,7 @@ static struct platform_driver generic_onenand_driver = { .remove = __devexit_p(generic_onenand_remove), }; -MODULE_ALIAS(DRIVER_NAME); +MODULE_ALIAS("platform:" DRIVER_NAME); static int __init generic_onenand_init(void) { diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 9f322f1a7f22..348ce7184295 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -815,7 +815,7 @@ static void __exit omap2_onenand_exit(void) module_init(omap2_onenand_init); module_exit(omap2_onenand_exit); -MODULE_ALIAS(DRIVER_NAME); +MODULE_ALIAS("platform:" DRIVER_NAME); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jarkko Lavinen "); MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP2 / OMAP3"); -- cgit v1.2.3 From 466f2609fe579b51358ea66774457962a860ddcc Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 9 Dec 2010 15:59:32 +0100 Subject: libata: no special completion processing for EH commands commit f08dc1ac6b15c681f4643d8da1700e06c3855608 upstream. ata_qc_complete() contains special handling for certain commands. For example, it schedules EH for device revalidation after certain configurations are changed. These shouldn't be applied to EH commands but they were. In most cases, it doesn't cause an actual problem because EH doesn't issue any command which would trigger special handling; however, ACPI can issue such commands via _GTF which can cause weird interactions. Restructure ata_qc_complete() such that EH commands are always passed on to __ata_qc_complete(). stable: Please apply to -stable only after 2.6.38 is released. Signed-off-by: Tejun Heo Signed-off-by: Andi Kleen Reported-by: Kyle McMartin Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-core.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 1f24267b6d2b..c77a16724440 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4946,9 +4946,6 @@ static void ata_verify_xfer(struct ata_queued_cmd *qc) { struct ata_device *dev = qc->dev; - if (ata_tag_internal(qc->tag)) - return; - if (ata_is_nodata(qc->tf.protocol)) return; @@ -4992,14 +4989,23 @@ void ata_qc_complete(struct ata_queued_cmd *qc) if (unlikely(qc->err_mask)) qc->flags |= ATA_QCFLAG_FAILED; - if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { - /* always fill result TF for failed qc */ + /* + * Finish internal commands without any further processing + * and always with the result TF filled. + */ + if (unlikely(ata_tag_internal(qc->tag))) { fill_result_tf(qc); + __ata_qc_complete(qc); + return; + } - if (!ata_tag_internal(qc->tag)) - ata_qc_schedule_eh(qc); - else - __ata_qc_complete(qc); + /* + * Non-internal qc has failed. Fill the result TF and + * summon EH. + */ + if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { + fill_result_tf(qc); + ata_qc_schedule_eh(qc); return; } -- cgit v1.2.3 From e5c30be3fa24a717a89a6ee9d0cd735e6002cdfd Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sun, 27 Feb 2011 19:53:53 +0100 Subject: MIPS: MTX-1: Make au1000_eth probe all PHY addresses commit bf3a1eb85967dcbaae42f4fcb53c2392cec32677 upstream. When au1000_eth probes the MII bus for PHY address, if we do not set au1000_eth platform data's phy_search_highest_address, the MII probing logic will exit early and will assume a valid PHY is found at address 0. For MTX-1, the PHY is at address 31, and without this patch, the link detection/speed/duplex would not work correctly. Signed-off-by: Florian Fainelli Signed-off-by: Andi Kleen To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2111/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman --- arch/mips/alchemy/mtx-1/platform.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/mips/alchemy/mtx-1/platform.c b/arch/mips/alchemy/mtx-1/platform.c index e30e42add697..956f946218c5 100644 --- a/arch/mips/alchemy/mtx-1/platform.c +++ b/arch/mips/alchemy/mtx-1/platform.c @@ -28,6 +28,8 @@ #include #include +#include + static struct gpio_keys_button mtx1_gpio_button[] = { { .gpio = 207, @@ -140,10 +142,17 @@ static struct __initdata platform_device * mtx1_devs[] = { &mtx1_mtd, }; +static struct au1000_eth_platform_data mtx1_au1000_eth0_pdata = { + .phy_search_highest_addr = 1, + .phy1_search_mac0 = 1, +}; + static int __init mtx1_register_devices(void) { int rc; + au1xxx_override_eth_cfg(0, &mtx1_au1000_eth0_pdata); + rc = gpio_request(mtx1_gpio_button[0].gpio, mtx1_gpio_button[0].desc); if (rc < 0) { -- cgit v1.2.3 From 7838ead2b8f913f82d2b1d7f51e12d9ff1d6d936 Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Wed, 9 Mar 2011 15:22:23 -0800 Subject: x86/mm: Handle mm_fault_error() in kernel space commit f86268549f424f83b9eb0963989270e14fbfc3de upstream. mm_fault_error() should not execute oom-killer, if page fault occurs in kernel space. E.g. in copy_from_user()/copy_to_user(). This would happen if we find ourselves in OOM on a copy_to_user(), or a copy_from_user() which faults. Without this patch, the kernels hangs up in copy_from_user(), because OOM killer sends SIG_KILL to current process, but it can't handle a signal while in syscall, then the kernel returns to copy_from_user(), reexcute current command and provokes page_fault again. With this patch the kernel return -EFAULT from copy_from_user(). The code, which checks that page fault occurred in kernel space, has been copied from do_sigbus(). This situation is handled by the same way on powerpc, xtensa, tile, ... Signed-off-by: Andrey Vagin Signed-off-by: Andrew Morton Signed-off-by: Andi Kleen Cc: "H. Peter Anvin" Cc: Linus Torvalds LKML-Reference: <201103092322.p29NMNPH001682@imap1.linux-foundation.org> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/fault.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 4c4508e8a204..544ed251a40c 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -831,6 +831,13 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, unsigned long address, unsigned int fault) { if (fault & VM_FAULT_OOM) { + /* Kernel mode? Handle exceptions or die: */ + if (!(error_code & PF_USER)) { + up_read(¤t->mm->mmap_sem); + no_context(regs, error_code, address); + return; + } + out_of_memory(regs, error_code, address); } else { if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON)) -- cgit v1.2.3 From 02966761c2632f7a15ecfc83bcd32b935ae84d3d Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 10 Feb 2011 21:26:13 -0500 Subject: ftrace: Fix memory leak with function graph and cpu hotplug commit 868baf07b1a259f5f3803c1dc2777b6c358f83cf upstream. When the fuction graph tracer starts, it needs to make a special stack for each task to save the real return values of the tasks. All running tasks have this stack created, as well as any new tasks. On CPU hot plug, the new idle task will allocate a stack as well when init_idle() is called. The problem is that cpu hotplug does not create a new idle_task. Instead it uses the idle task that existed when the cpu went down. ftrace_graph_init_task() will add a new ret_stack to the task that is given to it. Because a clone will make the task have a stack of its parent it does not check if the task's ret_stack is already NULL or not. When the CPU hotplug code starts a CPU up again, it will allocate a new stack even though one already existed for it. The solution is to treat the idle_task specially. In fact, the function_graph code already does, just not at init_idle(). Instead of using the ftrace_graph_init_task() for the idle task, which that function expects the task to be a clone, have a separate ftrace_graph_init_idle_task(). Also, we will create a per_cpu ret_stack that is used by the idle task. When we call ftrace_graph_init_idle_task() it will check if the idle task's ret_stack is NULL, if it is, then it will assign it the per_cpu ret_stack. Reported-by: Benjamin Herrenschmidt Suggested-by: Peter Zijlstra Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/linux/ftrace.h | 2 ++ kernel/sched.c | 2 +- kernel/trace/ftrace.c | 52 +++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 41e46330d9be..59c3939b5977 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -423,6 +423,7 @@ extern void unregister_ftrace_graph(void); extern void ftrace_graph_init_task(struct task_struct *t); extern void ftrace_graph_exit_task(struct task_struct *t); +extern void ftrace_graph_init_idle_task(struct task_struct *t, int cpu); static inline int task_curr_ret_stack(struct task_struct *t) { @@ -446,6 +447,7 @@ static inline void unpause_graph_tracing(void) static inline void ftrace_graph_init_task(struct task_struct *t) { } static inline void ftrace_graph_exit_task(struct task_struct *t) { } +static inline void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) { } static inline int register_ftrace_graph(trace_func_graph_ret_t retfunc, trace_func_graph_ent_t entryfunc) diff --git a/kernel/sched.c b/kernel/sched.c index 772b2d53cedb..d40d662392cf 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -5428,7 +5428,7 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu) * The idle tasks have their own, simple scheduling class: */ idle->sched_class = &idle_sched_class; - ftrace_graph_init_task(idle); + ftrace_graph_init_idle_task(idle, cpu); } /* diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 6b316b3928a3..d9aaa9b786eb 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3290,7 +3290,7 @@ static int start_graph_tracing(void) /* The cpu_boot init_task->ret_stack will never be freed */ for_each_online_cpu(cpu) { if (!idle_task(cpu)->ret_stack) - ftrace_graph_init_task(idle_task(cpu)); + ftrace_graph_init_idle_task(idle_task(cpu), cpu); } do { @@ -3380,6 +3380,49 @@ void unregister_ftrace_graph(void) mutex_unlock(&ftrace_lock); } +static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack); + +static void +graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack) +{ + atomic_set(&t->tracing_graph_pause, 0); + atomic_set(&t->trace_overrun, 0); + t->ftrace_timestamp = 0; + /* make curr_ret_stack visable before we add the ret_stack */ + smp_wmb(); + t->ret_stack = ret_stack; +} + +/* + * Allocate a return stack for the idle task. May be the first + * time through, or it may be done by CPU hotplug online. + */ +void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) +{ + t->curr_ret_stack = -1; + /* + * The idle task has no parent, it either has its own + * stack or no stack at all. + */ + if (t->ret_stack) + WARN_ON(t->ret_stack != per_cpu(idle_ret_stack, cpu)); + + if (ftrace_graph_active) { + struct ftrace_ret_stack *ret_stack; + + ret_stack = per_cpu(idle_ret_stack, cpu); + if (!ret_stack) { + ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH + * sizeof(struct ftrace_ret_stack), + GFP_KERNEL); + if (!ret_stack) + return; + per_cpu(idle_ret_stack, cpu) = ret_stack; + } + graph_init_task(t, ret_stack); + } +} + /* Allocate a return stack for newly created task */ void ftrace_graph_init_task(struct task_struct *t) { @@ -3395,12 +3438,7 @@ void ftrace_graph_init_task(struct task_struct *t) GFP_KERNEL); if (!ret_stack) return; - atomic_set(&t->tracing_graph_pause, 0); - atomic_set(&t->trace_overrun, 0); - t->ftrace_timestamp = 0; - /* make curr_ret_stack visable before we add the ret_stack */ - smp_wmb(); - t->ret_stack = ret_stack; + graph_init_task(t, ret_stack); } } -- cgit v1.2.3 From 190b6fa5f90830b1ea5abc1be50d8db69d07fb1b Mon Sep 17 00:00:00 2001 From: Kamal Mostafa Date: Thu, 3 Feb 2011 17:38:04 -0800 Subject: x86: Fix panic when handling "mem={invalid}" param commit 77eed821accf5dd962b1f13bed0680e217e49112 upstream. Avoid removing all of memory and panicing when "mem={invalid}" is specified, e.g. mem=blahblah, mem=0, or mem=nopentium (on platforms other than x86_32). Signed-off-by: Kamal Mostafa Signed-off-by: Andi Kleen BugLink: http://bugs.launchpad.net/bugs/553464 Cc: Yinghai Lu Cc: Len Brown Cc: Rafael J. Wysocki LKML-Reference: <1296783486-23033-1-git-send-email-kamal@canonical.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/e820.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 0d6fc71bedb1..305e3aa3f9f5 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -989,6 +989,9 @@ static int __init parse_memopt(char *p) userdef = 1; mem_size = memparse(p, &p); + /* don't remove all of memory when handling "mem={invalid}" param */ + if (mem_size == 0) + return -EINVAL; e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1); return 0; -- cgit v1.2.3 From 92c1022c321ea0a7d190d87a5cb3293226b24822 Mon Sep 17 00:00:00 2001 From: Kamal Mostafa Date: Thu, 3 Feb 2011 17:38:05 -0800 Subject: x86: Emit "mem=nopentium ignored" warning when not supported commit 9a6d44b9adb777ca9549e88cd55bd8f2673c52a2 upstream. Emit warning when "mem=nopentium" is specified on any arch other than x86_32 (the only that arch supports it). Signed-off-by: Kamal Mostafa Signed-off-by: Andi Kleen BugLink: http://bugs.launchpad.net/bugs/553464 Cc: Yinghai Lu Cc: Len Brown Cc: Rafael J. Wysocki LKML-Reference: <1296783486-23033-2-git-send-email-kamal@canonical.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/e820.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 305e3aa3f9f5..28b09af9775c 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -980,12 +980,15 @@ static int __init parse_memopt(char *p) if (!p) return -EINVAL; -#ifdef CONFIG_X86_32 if (!strcmp(p, "nopentium")) { +#ifdef CONFIG_X86_32 setup_clear_cpu_cap(X86_FEATURE_PSE); return 0; - } +#else + printk(KERN_WARNING "mem=nopentium ignored! (only supported on x86_32)\n"); + return -EINVAL; #endif + } userdef = 1; mem_size = memparse(p, &p); -- cgit v1.2.3 From af02964e201041e04b3e4af91f46a2473f8cd20b Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Thu, 9 Sep 2010 09:44:56 -0700 Subject: ahci: AHCI and RAID mode SATA patch for Intel Patsburg DeviceIDs commit 992b3fb9b5391bc4de5b42bb810dc6dd583a6c4a upstream. This patch adds the Intel Patsburg (PCH) SATA AHCI and RAID Controller DeviceIDs. Signed-off-by: Seth Heasley Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/ata/ahci.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index d571e3f24b32..e2f40f9cf1b0 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -248,6 +248,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */ { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ + { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ + { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ + { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, -- cgit v1.2.3 From 9af7029b95687b78d8529aad52945acc9fc04912 Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Mon, 10 Jan 2011 12:57:17 -0800 Subject: ahci: AHCI mode SATA patch for Intel DH89xxCC DeviceIDs commit a4a461a6df6c0481d5a3d61660ed97f5b539cf16 upstream. This patch adds the AHCI-mode SATA DeviceID for the Intel DH89xxCC PCH. Signed-off-by: Seth Heasley Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/ata/ahci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index e2f40f9cf1b0..d98861662428 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -251,6 +251,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ + { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, -- cgit v1.2.3 From f40668b7b5b2224c23826d5f1abe076c7563b98e Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Fri, 11 Mar 2011 11:57:42 -0800 Subject: ahci: AHCI mode SATA patch for Intel Patsburg SATA RAID controller commit 64a3903d0885879ba8706a8bcf71c5e3e7664db2 upstream. This patch adds an updated SATA RAID DeviceID for the Intel Patsburg PCH. Signed-off-by: Seth Heasley Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/ata/ahci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index d98861662428..deb228c98fc9 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -251,6 +251,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ + { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ -- cgit v1.2.3 From af8c55e566b98985bde53ce09e72afcc6db04d4f Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 23 Feb 2011 08:11:32 -0800 Subject: RDMA/cma: Fix crash in request handlers commit 25ae21a10112875763c18b385624df713a288a05 upstream. Doug Ledford and Red Hat reported a crash when running the rdma_cm on a real-time OS. The crash has the following call trace: cm_process_work cma_req_handler cma_disable_callback rdma_create_id kzalloc init_completion cma_get_net_info cma_save_net_info cma_any_addr cma_zero_addr rdma_translate_ip rdma_copy_addr cma_acquire_dev rdma_addr_get_sgid ib_find_cached_gid cma_attach_to_dev ucma_event_handler kzalloc ib_copy_ah_attr_to_user cma_comp [ preempted ] cma_write copy_from_user ucma_destroy_id copy_from_user _ucma_find_context ucma_put_ctx ucma_free_ctx rdma_destroy_id cma_exch cma_cancel_operation rdma_node_get_transport rt_mutex_slowunlock bad_area_nosemaphore oops_enter They were able to reproduce the crash multiple times with the following details: Crash seems to always happen on the: mutex_unlock(&conn_id->handler_mutex); as conn_id looks to have been freed during this code path. An examination of the code shows that a race exists in the request handlers. When a new connection request is received, the rdma_cm allocates a new connection identifier. This identifier has a single reference count on it. If a user calls rdma_destroy_id() from another thread after receiving a callback, rdma_destroy_id will proceed to destroy the id and free the associated memory. However, the request handlers may still be in the process of running. When control returns to the request handlers, they can attempt to access the newly created identifiers. Fix this by holding a reference on the newly created rdma_cm_id until the request handler is through accessing it. Signed-off-by: Sean Hefty Acked-by: Doug Ledford Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/infiniband/core/cma.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index b930b8110a63..2a072be195a3 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1136,6 +1136,11 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) cm_id->context = conn_id; cm_id->cm_handler = cma_ib_handler; + /* + * Protect against the user destroying conn_id from another thread + * until we're done accessing it. + */ + atomic_inc(&conn_id->refcount); ret = conn_id->id.event_handler(&conn_id->id, &event); if (!ret) { /* @@ -1148,8 +1153,10 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0); mutex_unlock(&lock); mutex_unlock(&conn_id->handler_mutex); + cma_deref_id(conn_id); goto out; } + cma_deref_id(conn_id); /* Destroy the CM ID by returning a non-zero value. */ conn_id->cm_id.ib = NULL; @@ -1351,17 +1358,25 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, event.param.conn.private_data_len = iw_event->private_data_len; event.param.conn.initiator_depth = attr.max_qp_init_rd_atom; event.param.conn.responder_resources = attr.max_qp_rd_atom; + + /* + * Protect against the user destroying conn_id from another thread + * until we're done accessing it. + */ + atomic_inc(&conn_id->refcount); ret = conn_id->id.event_handler(&conn_id->id, &event); if (ret) { /* User wants to destroy the CM ID */ conn_id->cm_id.iw = NULL; cma_exch(conn_id, CMA_DESTROYING); mutex_unlock(&conn_id->handler_mutex); + cma_deref_id(conn_id); rdma_destroy_id(&conn_id->id); goto out; } mutex_unlock(&conn_id->handler_mutex); + cma_deref_id(conn_id); out: if (dev) -- cgit v1.2.3 From ca78068b35522c820207b36191cba1385163f198 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 23 Feb 2011 08:17:40 -0800 Subject: IB/cm: Bump reference count on cm_id before invoking callback commit 29963437a48475036353b95ab142bf199adb909e upstream. When processing a SIDR REQ, the ib_cm allocates a new cm_id. The refcount of the cm_id is initialized to 1. However, cm_process_work will decrement the refcount after invoking all callbacks. The result is that the cm_id will end up with refcount set to 0 by the end of the sidr req handler. If a user tries to destroy the cm_id, the destruction will proceed, under the incorrect assumption that no other threads are referencing the cm_id. This can lead to a crash when the cm callback thread tries to access the cm_id. This problem was noticed as part of a larger investigation with kernel crashes in the rdma_cm when running on a real time OS. Signed-off-by: Sean Hefty Acked-by: Doug Ledford Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/infiniband/core/cm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index ad63b79afac1..24229453b1ae 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -2987,6 +2987,7 @@ static int cm_sidr_req_handler(struct cm_work *work) goto out; /* No match. */ } atomic_inc(&cur_cm_id_priv->refcount); + atomic_inc(&cm_id_priv->refcount); spin_unlock_irq(&cm.lock); cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler; -- cgit v1.2.3 From b0a8120fc5cd5bb4e74c2b94c8e2445b49cf51de Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Tue, 15 Mar 2011 15:31:37 +0100 Subject: x86, quirk: Fix SB600 revision check commit 1d3e09a304e6c4e004ca06356578b171e8735d3c upstream. Commit 7f74f8f28a2bd9db9404f7d364e2097a0c42cc12 (x86 quirk: Fix polarity for IRQ0 pin2 override on SB800 systems) introduced a regression. It removed some SB600 specific code to determine the revision ID without adapting a corresponding revision ID check for SB600. See this mail thread: http://marc.info/?l=linux-kernel&m=129980296006380&w=2 This patch adapts the corresponding check to cover all SB600 revisions. Tested-by: Wang Lei Signed-off-by: Andreas Herrmann Signed-off-by: Andi Kleen Cc: Andrew Morton LKML-Reference: <20110315143137.GD29499@alberich.amd.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/early-quirks.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index ef01d3d6a5a9..f67a33c7f415 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -161,7 +161,12 @@ static void __init ati_bugs_contd(int num, int slot, int func) if (rev >= 0x40) acpi_fix_pin2_polarity = 1; - if (rev > 0x13) + /* + * SB600: revisions 0x11, 0x12, 0x13, 0x14, ... + * SB700: revisions 0x39, 0x3a, ... + * SB800: revisions 0x40, 0x41, ... + */ + if (rev >= 0x39) return; if (acpi_use_timer_override) -- cgit v1.2.3 From 37e1711cff542c857e3c95ed0e6ac6c09ac819ef Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Wed, 22 Dec 2010 21:14:20 +0530 Subject: ath9k_hw: Fix incorrect macversion and macrev checks commit ac45c12dfb3f727a5a7a3332ed9c11b4a5ab287e upstream. There are few places where we are checking for macversion and revsions before RTC is powered ON. However we are reading the macversion and revisions only after RTC is powered ON and so both macversion and revisions are actully zero and this leads to incorrect srev checks Incorrect srev checks can cause registers to be configured wrongly and can cause unexpected behavior. Fixing this seems to address the ASPM issue that we have observed. The laptop becomes very slow and hangs mostly with ASPM L1 enabled without this fix. fix this by reading the macversion and revisisons even before we start using them. There is no reason why should we delay reading this info until RTC is powered on as this is just a register information. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/ath/ath9k/hw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2feee1ddb50d..4b9378f7d055 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -519,6 +519,8 @@ static int __ath9k_hw_init(struct ath_hw *ah) if (ah->hw_version.devid == AR5416_AR9100_DEVID) ah->hw_version.macVersion = AR_SREV_VERSION_9100; + ath9k_hw_read_revisions(ah); + if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { ath_print(common, ATH_DBG_FATAL, "Couldn't reset chip\n"); @@ -1096,8 +1098,6 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) return false; } - ath9k_hw_read_revisions(ah); - return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM); } -- cgit v1.2.3 From e688c3c8e6031059fbea2ebdb2f07948280a9561 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 28 Feb 2011 10:34:06 +0100 Subject: USB: serial/kobil_sct, fix potential tty NULL dereference commit 6960f40a954619857e7095a6179eef896f297077 upstream. Make sure that we check the return value of tty_port_tty_get. Sometimes it may return NULL and we later dereference that. The only place here is in kobil_read_int_callback, so fix it. Signed-off-by: Jiri Slaby Signed-off-by: Andi Kleen Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/kobil_sct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index bd5bd8589e04..b382d9a0274d 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -372,7 +372,7 @@ static void kobil_read_int_callback(struct urb *urb) } tty = tty_port_tty_get(&port->port); - if (urb->actual_length) { + if (tty && urb->actual_length) { /* BEGIN DEBUG */ /* -- cgit v1.2.3 From eefbb867d84225d11fe5ea7367cef079addca9d4 Mon Sep 17 00:00:00 2001 From: wangyanqing Date: Fri, 11 Mar 2011 06:24:38 -0800 Subject: USB: serial: ch341: add new id commit d0781383038e983a63843a9a6a067ed781db89c1 upstream. I picked up a new DAK-780EX(professional digitl reverb/mix system), which use CH341T chipset to communication with computer on 3/2011 and the CH341T's vendor code is 1a86 Looking up the CH341T's vendor and product id's I see: 1a86 QinHeng Electronics 5523 CH341 in serial mode, usb to serial port converter CH341T,CH341 are the products of the same company, maybe have some common hardware, and I test the ch341.c works well with CH341T Cc: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/ch341.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 7b8815ddf368..14ac87ee9251 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -75,6 +75,7 @@ static int debug; static const struct usb_device_id id_table[] = { { USB_DEVICE(0x4348, 0x5523) }, { USB_DEVICE(0x1a86, 0x7523) }, + { USB_DEVICE(0x1a86, 0x5523) }, { }, }; MODULE_DEVICE_TABLE(usb, id_table); -- cgit v1.2.3 From b543907c05b156ddf349ff966fb318de089520e7 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 23 Feb 2011 18:12:29 -0800 Subject: xhci: Fix cycle bit calculation during stall handling. commit 01a1fdb9a7afa5e3c14c9316d6f380732750b4e4 upstream. When an endpoint stalls, we need to update the xHCI host's internal dequeue pointer to move it past the stalled transfer. This includes updating the cycle bit (TRB ownership bit) if we have moved the dequeue pointer past a link TRB with the toggle cycle bit set. When we're trying to find the new dequeue segment, find_trb_seg() is supposed to keep track of whether we've passed any link TRBs with the toggle cycle bit set. However, this while loop's body while (cur_seg->trbs > trb || &cur_seg->trbs[TRBS_PER_SEGMENT - 1] < trb) { Will never get executed if the ring only contains one segment. find_trb_seg() will return immediately, without updating the new cycle bit. Since find_trb_seg() has no idea where in the segment the TD that stalled was, make the caller, xhci_find_new_dequeue_state(), check for this special case and update the cycle bit accordingly. This patch should be queued to kernels all the way back to 2.6.31. Signed-off-by: Sarah Sharp Tested-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/xhci-ring.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 4723a400d868..3562ba23e39b 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -483,6 +483,20 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, state->new_cycle_state = ~(state->new_cycle_state) & 0x1; next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr); + /* + * If there is only one segment in a ring, find_trb_seg()'s while loop + * will not run, and it will return before it has a chance to see if it + * needs to toggle the cycle bit. It can't tell if the stalled transfer + * ended just before the link TRB on a one-segment ring, or if the TD + * wrapped around the top of the ring, because it doesn't have the TD in + * question. Look for the one-segment case where stalled TRB's address + * is greater than the new dequeue pointer address. + */ + if (ep_ring->first_seg == ep_ring->first_seg->next && + state->new_deq_ptr < dev->eps[ep_index].stopped_trb) + state->new_cycle_state ^= 0x1; + xhci_dbg(xhci, "Cycle state = 0x%x\n", state->new_cycle_state); + /* Don't update the ring cycle state for the producer (us). */ xhci_dbg(xhci, "New dequeue segment = %p (virtual)\n", state->new_deq_seg); -- cgit v1.2.3 From eff1214a95e75a52b0fd6220bd92bab8d849e9b8 Mon Sep 17 00:00:00 2001 From: Vitaliy Kulikov Date: Wed, 9 Mar 2011 19:47:43 -0600 Subject: ALSA: hda - fix digital mic selection in mixer on 92HD8X codecs commit 094a42452abd5564429045e210281c6d22e67fca upstream. When the mux for digital mic is different from the mux for other mics, the current auto-parser doesn't handle them in a right way but provides only one mic. This patch fixes the issue. Signed-off-by: Vitaliy Kulikov Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_sigmatel.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 364848ef02ff..3532d2c37838 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -737,7 +737,7 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e struct sigmatel_spec *spec = codec->spec; unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); const struct hda_input_mux *imux = spec->input_mux; - unsigned int idx, prev_idx; + unsigned int idx, prev_idx, didx; idx = ucontrol->value.enumerated.item[0]; if (idx >= imux->num_items) @@ -749,7 +749,8 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e snd_hda_codec_write_cache(codec, spec->mux_nids[adc_idx], 0, AC_VERB_SET_CONNECT_SEL, imux->items[idx].index); - if (prev_idx >= spec->num_analog_muxes) { + if (prev_idx >= spec->num_analog_muxes && + spec->mux_nids[adc_idx] != spec->dmux_nids[adc_idx]) { imux = spec->dinput_mux; /* 0 = analog */ snd_hda_codec_write_cache(codec, @@ -759,9 +760,13 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e } } else { imux = spec->dinput_mux; + /* first dimux item is hardcoded to select analog imux, + * so lets skip it + */ + didx = idx - spec->num_analog_muxes + 1; snd_hda_codec_write_cache(codec, spec->dmux_nids[adc_idx], 0, AC_VERB_SET_CONNECT_SEL, - imux->items[idx - 1].index); + imux->items[didx].index); } spec->cur_mux[adc_idx] = idx; return 1; -- cgit v1.2.3 From e32a55e626737a1e5ccf42ebaa89070084125788 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 28 Feb 2011 10:45:09 +0100 Subject: PCI: add more checking to ICH region quirks commit cdb9755849fbaf2bb9c0a009ba5baa817a0f152d upstream. Per ICH4 and ICH6 specs, ACPI and GPIO regions are valid iff ACPI_EN and GPIO_EN bits are set to 1. Add checks for these bits into the quirks prior to the region creation. While at it, name the constants by macros. Signed-off-by: Jiri Slaby Signed-off-by: Andi Kleen Cc: Bjorn Helgaas Cc: "David S. Miller" Cc: Thomas Renninger Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 45 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 0e9acdefb13d..55d4093bf583 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -519,6 +519,17 @@ static void __devinit quirk_piix4_acpi(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, quirk_piix4_acpi); +#define ICH_PMBASE 0x40 +#define ICH_ACPI_CNTL 0x44 +#define ICH4_ACPI_EN 0x10 +#define ICH6_ACPI_EN 0x80 +#define ICH4_GPIOBASE 0x58 +#define ICH4_GPIO_CNTL 0x5c +#define ICH4_GPIO_EN 0x10 +#define ICH6_GPIOBASE 0x48 +#define ICH6_GPIO_CNTL 0x4c +#define ICH6_GPIO_EN 0x10 + /* * ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at * 0x40 (128 bytes of ACPI, GPIO & TCO registers) @@ -527,12 +538,21 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, qui static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev) { u32 region; + u8 enable; - pci_read_config_dword(dev, 0x40, ®ion); - quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH4 ACPI/GPIO/TCO"); + pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable); + if (enable & ICH4_ACPI_EN) { + pci_read_config_dword(dev, ICH_PMBASE, ®ion); + quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, + "ICH4 ACPI/GPIO/TCO"); + } - pci_read_config_dword(dev, 0x58, ®ion); - quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH4 GPIO"); + pci_read_config_byte(dev, ICH4_GPIO_CNTL, &enable); + if (enable & ICH4_GPIO_EN) { + pci_read_config_dword(dev, ICH4_GPIOBASE, ®ion); + quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES + 1, + "ICH4 GPIO"); + } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, quirk_ich4_lpc_acpi); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, quirk_ich4_lpc_acpi); @@ -548,12 +568,21 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, qui static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev) { u32 region; + u8 enable; - pci_read_config_dword(dev, 0x40, ®ion); - quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH6 ACPI/GPIO/TCO"); + pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable); + if (enable & ICH6_ACPI_EN) { + pci_read_config_dword(dev, ICH_PMBASE, ®ion); + quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, + "ICH6 ACPI/GPIO/TCO"); + } - pci_read_config_dword(dev, 0x48, ®ion); - quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO"); + pci_read_config_byte(dev, ICH6_GPIO_CNTL, &enable); + if (enable & ICH4_GPIO_EN) { + pci_read_config_dword(dev, ICH6_GPIOBASE, ®ion); + quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES + 1, + "ICH6 GPIO"); + } } static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize) -- cgit v1.2.3 From 7d6fac3aa14a7d8248b34d5d5ca2c9947e1e8ab6 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 28 Feb 2011 10:45:10 +0100 Subject: PCI: do not create quirk I/O regions below PCIBIOS_MIN_IO for ICH commit 87e3dc3855430bd254370afc79f2ed92250f5b7c upstream. Some broken BIOSes on ICH4 chipset report an ACPI region which is in conflict with legacy IDE ports when ACPI is disabled. Even though the regions overlap, IDE ports are working correctly (we cannot find out the decoding rules on chipsets). So the only problem is the reported region itself, if we don't reserve the region in the quirk everything works as expected. This patch avoids reserving any quirk regions below PCIBIOS_MIN_IO which is 0x1000. Some regions might be (and are by a fast google query) below this border, but the only difference is that they won't be reserved anymore. They should still work though the same as before. The conflicts look like (1f.0 is bridge, 1f.1 is IDE ctrl): pci 0000:00:1f.1: address space collision: [io 0x0170-0x0177] conflicts with 0000:00:1f.0 [io 0x0100-0x017f] At 0x0100 a 128 bytes long ACPI region is reported in the quirk for ICH4. ata_piix then fails to find disks because the IDE legacy ports are zeroed: ata_piix 0000:00:1f.1: device not available (can't reserve [io 0x0000-0x0007]) References: https://bugzilla.novell.com/show_bug.cgi?id=558740 Signed-off-by: Jiri Slaby Signed-off-by: Andi Kleen Cc: Bjorn Helgaas Cc: "David S. Miller" Cc: Thomas Renninger Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 55d4093bf583..9cd70007d936 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -540,18 +540,30 @@ static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev) u32 region; u8 enable; + /* + * The check for PCIBIOS_MIN_IO is to ensure we won't create a conflict + * with low legacy (and fixed) ports. We don't know the decoding + * priority and can't tell whether the legacy device or the one created + * here is really at that address. This happens on boards with broken + * BIOSes. + */ + pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable); if (enable & ICH4_ACPI_EN) { pci_read_config_dword(dev, ICH_PMBASE, ®ion); - quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, - "ICH4 ACPI/GPIO/TCO"); + region &= PCI_BASE_ADDRESS_IO_MASK; + if (region >= PCIBIOS_MIN_IO) + quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, + "ICH4 ACPI/GPIO/TCO"); } pci_read_config_byte(dev, ICH4_GPIO_CNTL, &enable); if (enable & ICH4_GPIO_EN) { pci_read_config_dword(dev, ICH4_GPIOBASE, ®ion); - quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES + 1, - "ICH4 GPIO"); + region &= PCI_BASE_ADDRESS_IO_MASK; + if (region >= PCIBIOS_MIN_IO) + quirk_io_region(dev, region, 64, + PCI_BRIDGE_RESOURCES + 1, "ICH4 GPIO"); } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, quirk_ich4_lpc_acpi); @@ -573,15 +585,19 @@ static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev) pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable); if (enable & ICH6_ACPI_EN) { pci_read_config_dword(dev, ICH_PMBASE, ®ion); - quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, - "ICH6 ACPI/GPIO/TCO"); + region &= PCI_BASE_ADDRESS_IO_MASK; + if (region >= PCIBIOS_MIN_IO) + quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, + "ICH6 ACPI/GPIO/TCO"); } pci_read_config_byte(dev, ICH6_GPIO_CNTL, &enable); if (enable & ICH4_GPIO_EN) { pci_read_config_dword(dev, ICH6_GPIOBASE, ®ion); - quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES + 1, - "ICH6 GPIO"); + region &= PCI_BASE_ADDRESS_IO_MASK; + if (region >= PCIBIOS_MIN_IO) + quirk_io_region(dev, region, 64, + PCI_BRIDGE_RESOURCES + 1, "ICH6 GPIO"); } } -- cgit v1.2.3 From 7a0c7104fc7aba88bfc8138224f5ee2f2391ce28 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 13 Jan 2011 19:47:56 +0000 Subject: PCI: sysfs: Fix failure path for addition of "vpd" attribute commit 0f12a4e29368a9476076515881d9ef4e5876c6e2 upstream. Commit 280c73d ("PCI: centralize the capabilities code in pci-sysfs.c") changed the initialisation of the "rom" and "vpd" attributes, and made the failure path for the "vpd" attribute incorrect. We must free the new attribute structure (attr), but instead we currently free dev->vpd->attr. That will normally be NULL, resulting in a memory leak, but it might be a stale pointer, resulting in a double-free. Found by inspection; compile-tested only. Signed-off-by: Ben Hutchings Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/pci/pci-sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 3d9f3eb45082..d4ad1bd20ac5 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -1018,7 +1018,7 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev) attr->write = write_vpd_attr; retval = sysfs_create_bin_file(&dev->dev.kobj, attr); if (retval) { - kfree(dev->vpd->attr); + kfree(attr); return retval; } dev->vpd->attr = attr; -- cgit v1.2.3 From 3a5487a6be67115e24c164f80be511fe6d6b98d7 Mon Sep 17 00:00:00 2001 From: Przemyslaw Bruski Date: Sun, 13 Mar 2011 16:18:56 +0100 Subject: ALSA: ctxfi - Fix incorrect SPDIF status bit mask commit 4c1847e884efddcc3ede371f7839e5e65b25c34d upstream. SPDIF status mask creation was incorrect. Signed-off-by: Przemyslaw Bruski Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/ctxfi/ctatc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 1bff80cde0a2..b9321544c31c 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -869,7 +869,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm) mutex_lock(&atc->atc_mutex); dao->ops->get_spos(dao, &status); if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) { - status &= ((~IEC958_AES3_CON_FS) << 24); + status &= ~(IEC958_AES3_CON_FS << 24); status |= (iec958_con_fs << 24); dao->ops->set_spos(dao, status); dao->ops->commit_write(dao); -- cgit v1.2.3 From 99cf93e9b9e67fd1ac9d2067c6fe42f167fe81c3 Mon Sep 17 00:00:00 2001 From: Przemyslaw Bruski Date: Sun, 13 Mar 2011 16:18:57 +0100 Subject: ALSA: ctxfi - Fix SPDIF status retrieval commit f164753a263bfd2daaf3e0273b179de7e099c57d upstream. SDPIF status retrieval always returned the default settings instead of the actual ones. Signed-off-by: Przemyslaw Bruski Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/ctxfi/ctmixer.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c index 15c1e7271ea8..c3519ff42fbb 100644 --- a/sound/pci/ctxfi/ctmixer.c +++ b/sound/pci/ctxfi/ctmixer.c @@ -566,19 +566,6 @@ static int ct_spdif_get_mask(struct snd_kcontrol *kcontrol, return 0; } -static int ct_spdif_default_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned int status = SNDRV_PCM_DEFAULT_CON_SPDIF; - - ucontrol->value.iec958.status[0] = (status >> 0) & 0xff; - ucontrol->value.iec958.status[1] = (status >> 8) & 0xff; - ucontrol->value.iec958.status[2] = (status >> 16) & 0xff; - ucontrol->value.iec958.status[3] = (status >> 24) & 0xff; - - return 0; -} - static int ct_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -586,6 +573,10 @@ static int ct_spdif_get(struct snd_kcontrol *kcontrol, unsigned int status; atc->spdif_out_get_status(atc, &status); + + if (status == 0) + status = SNDRV_PCM_DEFAULT_CON_SPDIF; + ucontrol->value.iec958.status[0] = (status >> 0) & 0xff; ucontrol->value.iec958.status[1] = (status >> 8) & 0xff; ucontrol->value.iec958.status[2] = (status >> 16) & 0xff; @@ -629,7 +620,7 @@ static struct snd_kcontrol_new iec958_default_ctl = { .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), .count = 1, .info = ct_spdif_info, - .get = ct_spdif_default_get, + .get = ct_spdif_get, .put = ct_spdif_put, .private_value = MIXER_IEC958_DEFAULT }; -- cgit v1.2.3 From 5989dd43dff051d62fea4ea5f730dec9c9acb3c1 Mon Sep 17 00:00:00 2001 From: Przemyslaw Bruski Date: Sun, 13 Mar 2011 16:18:58 +0100 Subject: ALSA: ctxfi - Clear input settings before initialization commit efed5f26664f93991c929d5bb343e65f900d72bc upstream. Clear input settings before initialization. Signed-off-by: Przemyslaw Bruski Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/ctxfi/ctdaio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c index af56eb949bde..47d9ea97de02 100644 --- a/sound/pci/ctxfi/ctdaio.c +++ b/sound/pci/ctxfi/ctdaio.c @@ -176,6 +176,7 @@ static int dao_set_left_input(struct dao *dao, struct rsc *input) if (!entry) return -ENOMEM; + dao->ops->clear_left_input(dao); /* Program master and conjugate resources */ input->ops->master(input); daio->rscl.ops->master(&daio->rscl); @@ -204,6 +205,7 @@ static int dao_set_right_input(struct dao *dao, struct rsc *input) if (!entry) return -ENOMEM; + dao->ops->clear_right_input(dao); /* Program master and conjugate resources */ input->ops->master(input); daio->rscr.ops->master(&daio->rscr); -- cgit v1.2.3 From 7d88d3b036943c87750745bded1d39fb76691b9c Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 15 Mar 2011 19:56:30 -0400 Subject: SUNRPC: Ensure we always run the tk_callback before tk_action commit e020c6800c9621a77223bf2c1ff68180e41e8ebf upstream. This fixes a race in which the task->tk_callback() puts the rpc_task to sleep, setting a new callback. Under certain circumstances, the current code may end up executing the task->tk_action before it gets round to the callback. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/sunrpc/sched.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 4a843b883b89..c55f753b09c0 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -637,14 +637,12 @@ static void __rpc_execute(struct rpc_task *task) save_callback = task->tk_callback; task->tk_callback = NULL; save_callback(task); - } - - /* - * Perform the next FSM step. - * tk_action may be NULL when the task has been killed - * by someone else. - */ - if (!RPC_IS_QUEUED(task)) { + } else { + /* + * Perform the next FSM step. + * tk_action may be NULL when the task has been killed + * by someone else. + */ if (task->tk_action == NULL) break; task->tk_action(task); -- cgit v1.2.3 From 09d55df69df7b1b5500fdca8f40c7955342213be Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 9 Mar 2011 14:38:42 +1100 Subject: perf, powerpc: Handle events that raise an exception without overflowing commit 0837e3242c73566fc1c0196b4ec61779c25ffc93 upstream. Events on POWER7 can roll back if a speculative event doesn't eventually complete. Unfortunately in some rare cases they will raise a performance monitor exception. We need to catch this to ensure we reset the PMC. In all cases the PMC will be 256 or less cycles from overflow. Signed-off-by: Anton Blanchard Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen LKML-Reference: <20110309143842.6c22845e@kryten> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/include/asm/reg.h | 1 + arch/powerpc/kernel/perf_event.c | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index d62fdf4e504b..1dc338c1996d 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -878,6 +878,7 @@ #define PV_970 0x0039 #define PV_POWER5 0x003A #define PV_POWER5p 0x003B +#define PV_POWER7 0x003F #define PV_970FX 0x003C #define PV_630 0x0040 #define PV_630p 0x0041 diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c index 5c14ffe51258..59f246792746 100644 --- a/arch/powerpc/kernel/perf_event.c +++ b/arch/powerpc/kernel/perf_event.c @@ -1230,6 +1230,28 @@ unsigned long perf_instruction_pointer(struct pt_regs *regs) return ip; } +static bool pmc_overflow(unsigned long val) +{ + if ((int)val < 0) + return true; + + /* + * Events on POWER7 can roll back if a speculative event doesn't + * eventually complete. Unfortunately in some rare cases they will + * raise a performance monitor exception. We need to catch this to + * ensure we reset the PMC. In all cases the PMC will be 256 or less + * cycles from overflow. + * + * We only do this if the first pass fails to find any overflowing + * PMCs because a user might set a period of less than 256 and we + * don't want to mistakenly reset them. + */ + if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256)) + return true; + + return false; +} + /* * Performance monitor interrupt stuff */ @@ -1277,7 +1299,7 @@ static void perf_event_interrupt(struct pt_regs *regs) if (is_limited_pmc(i + 1)) continue; val = read_pmc(i + 1); - if ((int)val < 0) + if (pmc_overflow(val)) write_pmc(i + 1, 0); } } -- cgit v1.2.3 From 72c399c6add21b6cd912a085a1b1f00751fbbcf1 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Fri, 4 Mar 2011 16:04:08 -0600 Subject: ext3: Always set dx_node's fake_dirent explicitly. commit d7433142b63d727b5a217c37b1a1468b116a9771 upstream. (crossport of 1f7bebb9e911d870fa8f997ddff838e82b5715ea by Andreas Schlick ) When ext3_dx_add_entry() has to split an index node, it has to ensure that name_len of dx_node's fake_dirent is also zero, because otherwise e2fsck won't recognise it as an intermediate htree node and consider the htree to be corrupted. Signed-off-by: Eric Sandeen Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ext3/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index ee184084ca42..827b5736a4f8 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -1550,8 +1550,8 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, goto cleanup; node2 = (struct dx_node *)(bh2->b_data); entries2 = node2->entries; + memset(&node2->fake, 0, sizeof(struct fake_dirent)); node2->fake.rec_len = ext3_rec_len_to_disk(sb->s_blocksize); - node2->fake.inode = 0; BUFFER_TRACE(frame->bh, "get_write_access"); err = ext3_journal_get_write_access(handle, frame->bh); if (err) -- cgit v1.2.3 From d3b50d91a9aa573aef712e372764521189146a81 Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Tue, 15 Mar 2011 13:27:16 -0600 Subject: call_function_many: fix list delete vs add race commit e6cd1e07a185d5f9b0aa75e020df02d3c1c44940 upstream. Peter pointed out there was nothing preventing the list_del_rcu in smp_call_function_interrupt from running before the list_add_rcu in smp_call_function_many. Fix this by not setting refs until we have gotten the lock for the list. Take advantage of the wmb in list_add_rcu to save an explicit additional one. I tried to force this race with a udelay before the lock & list_add and by mixing all 64 online cpus with just 3 random cpus in the mask, but was unsuccessful. Still, inspection shows a valid race, and the fix is a extension of the existing protection window in the current code. Reported-by: Peter Zijlstra Signed-off-by: Milton Miller Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/smp.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/kernel/smp.c b/kernel/smp.c index 3812b02f9e85..eea9665a0255 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -468,14 +468,15 @@ void smp_call_function_many(const struct cpumask *mask, cpumask_clear_cpu(this_cpu, data->cpumask); /* - * To ensure the interrupt handler gets an complete view - * we order the cpumask and refs writes and order the read - * of them in the interrupt handler. In addition we may - * only clear our own cpu bit from the mask. + * We reuse the call function data without waiting for any grace + * period after some other cpu removes it from the global queue. + * This means a cpu might find our data block as it is writen. + * The interrupt handler waits until it sees refs filled out + * while its cpu mask bit is set; here we may only clear our + * own cpu mask bit, and must wait to set refs until we are sure + * previous writes are complete and we have obtained the lock to + * add the element to the queue. */ - smp_wmb(); - - atomic_set(&data->refs, cpumask_weight(data->cpumask)); raw_spin_lock_irqsave(&call_function.lock, flags); /* @@ -484,6 +485,11 @@ void smp_call_function_many(const struct cpumask *mask, * will not miss any other list entries: */ list_add_rcu(&data->csd.list, &call_function.queue); + /* + * We rely on the wmb() in list_add_rcu to order the writes + * to func, data, and cpumask before this write to refs. + */ + atomic_set(&data->refs, cpumask_weight(data->cpumask)); raw_spin_unlock_irqrestore(&call_function.lock, flags); /* -- cgit v1.2.3 From 2926c9ad1f0e8b8b0957f84e533403d6dc9514db Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Tue, 15 Mar 2011 13:27:16 -0600 Subject: call_function_many: add missing ordering commit 45a5791920ae643eafc02e2eedef1a58e341b736 upstream. Paul McKenney's review pointed out two problems with the barriers in the 2.6.38 update to the smp call function many code. First, a barrier that would force the func and info members of data to be visible before their consumption in the interrupt handler was missing. This can be solved by adding a smp_wmb between setting the func and info members and setting setting the cpumask; this will pair with the existing and required smp_rmb ordering the cpumask read before the read of refs. This placement avoids the need a second smp_rmb in the interrupt handler which would be executed on each of the N cpus executing the call request. (I was thinking this barrier was present but was not). Second, the previous write to refs (establishing the zero that we the interrupt handler was testing from all cpus) was performed by a third party cpu. This would invoke transitivity which, as a recient or concurrent addition to memory-barriers.txt now explicitly states, would require a full smp_mb(). However, we know the cpumask will only be set by one cpu (the data owner) and any preivous iteration of the mask would have cleared by the reading cpu. By redundantly writing refs to 0 on the owning cpu before the smp_wmb, the write to refs will follow the same path as the writes that set the cpumask, which in turn allows us to keep the barrier in the interrupt handler a smp_rmb instead of promoting it to a smp_mb (which will be be executed by N cpus for each of the possible M elements on the list). I moved and expanded the comment about our (ab)use of the rcu list primitives for the concurrent walk earlier into this function. I considered moving the first two paragraphs to the queue list head and lock, but felt it would have been too disconected from the code. Cc: Paul McKinney Signed-off-by: Milton Miller Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/smp.c | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/kernel/smp.c b/kernel/smp.c index eea9665a0255..f697ca9ea975 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -460,23 +460,42 @@ void smp_call_function_many(const struct cpumask *mask, data = &__get_cpu_var(cfd_data); csd_lock(&data->csd); - BUG_ON(atomic_read(&data->refs) || !cpumask_empty(data->cpumask)); - data->csd.func = func; - data->csd.info = info; - cpumask_and(data->cpumask, mask, cpu_online_mask); - cpumask_clear_cpu(this_cpu, data->cpumask); + /* This BUG_ON verifies our reuse assertions and can be removed */ + BUG_ON(atomic_read(&data->refs) || !cpumask_empty(data->cpumask)); /* + * The global call function queue list add and delete are protected + * by a lock, but the list is traversed without any lock, relying + * on the rcu list add and delete to allow safe concurrent traversal. * We reuse the call function data without waiting for any grace * period after some other cpu removes it from the global queue. - * This means a cpu might find our data block as it is writen. - * The interrupt handler waits until it sees refs filled out - * while its cpu mask bit is set; here we may only clear our - * own cpu mask bit, and must wait to set refs until we are sure - * previous writes are complete and we have obtained the lock to - * add the element to the queue. + * This means a cpu might find our data block as it is being + * filled out. + * + * We hold off the interrupt handler on the other cpu by + * ordering our writes to the cpu mask vs our setting of the + * refs counter. We assert only the cpu owning the data block + * will set a bit in cpumask, and each bit will only be cleared + * by the subject cpu. Each cpu must first find its bit is + * set and then check that refs is set indicating the element is + * ready to be processed, otherwise it must skip the entry. + * + * On the previous iteration refs was set to 0 by another cpu. + * To avoid the use of transitivity, set the counter to 0 here + * so the wmb will pair with the rmb in the interrupt handler. */ + atomic_set(&data->refs, 0); /* convert 3rd to 1st party write */ + + data->csd.func = func; + data->csd.info = info; + + /* Ensure 0 refs is visible before mask. Also orders func and info */ + smp_wmb(); + + /* We rely on the "and" being processed before the store */ + cpumask_and(data->cpumask, mask, cpu_online_mask); + cpumask_clear_cpu(this_cpu, data->cpumask); raw_spin_lock_irqsave(&call_function.lock, flags); /* @@ -486,8 +505,9 @@ void smp_call_function_many(const struct cpumask *mask, */ list_add_rcu(&data->csd.list, &call_function.queue); /* - * We rely on the wmb() in list_add_rcu to order the writes - * to func, data, and cpumask before this write to refs. + * We rely on the wmb() in list_add_rcu to complete our writes + * to the cpumask before this write to refs, which indicates + * data is on the list and is ready to be processed. */ atomic_set(&data->refs, cpumask_weight(data->cpumask)); raw_spin_unlock_irqrestore(&call_function.lock, flags); -- cgit v1.2.3 From 8dd765de113ce62bae99052a56c1f03f82f489cb Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Wed, 16 Mar 2011 11:37:29 +0800 Subject: x86: Flush TLB if PGD entry is changed in i386 PAE mode commit 4981d01eada5354d81c8929d5b2836829ba3df7b upstream. According to intel CPU manual, every time PGD entry is changed in i386 PAE mode, we need do a full TLB flush. Current code follows this and there is comment for this too in the code. But current code misses the multi-threaded case. A changed page table might be used by several CPUs, every such CPU should flush TLB. Usually this isn't a problem, because we prepopulate all PGD entries at process fork. But when the process does munmap and follows new mmap, this issue will be triggered. When it happens, some CPUs keep doing page faults: http://marc.info/?l=linux-kernel&m=129915020508238&w=2 Reported-by: Yasunori Goto Tested-by: Yasunori Goto Signed-off-by: Andi Kleen Reviewed-by: Rik van Riel Signed-off-by: Shaohua Li Cc: Mallick Asit K Cc: Linus Torvalds Cc: Andrew Morton Cc: linux-mm LKML-Reference: <1300246649.2337.95.camel@sli10-conroe> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/pgtable-3level.h | 11 +++-------- arch/x86/mm/pgtable.c | 3 +-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index 177b0165ea01..33927d283c92 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -69,8 +69,6 @@ static inline void native_pmd_clear(pmd_t *pmd) static inline void pud_clear(pud_t *pudp) { - unsigned long pgd; - set_pud(pudp, __pud(0)); /* @@ -79,13 +77,10 @@ static inline void pud_clear(pud_t *pudp) * section 8.1: in PAE mode we explicitly have to flush the * TLB via cr3 if the top-level pgd is changed... * - * Make sure the pud entry we're updating is within the - * current pgd to avoid unnecessary TLB flushes. + * Currently all places where pud_clear() is called either have + * flush_tlb_mm() followed or don't need TLB flush (x86_64 code or + * pud_clear_bad()), so we don't need TLB flush here. */ - pgd = read_cr3(); - if (__pa(pudp) >= pgd && __pa(pudp) < - (pgd + sizeof(pgd_t)*PTRS_PER_PGD)) - write_cr3(pgd); } #ifdef CONFIG_SMP diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index 5c4ee422590e..2a72049068e7 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c @@ -160,8 +160,7 @@ void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd) * section 8.1: in PAE mode we explicitly have to flush the * TLB via cr3 if the top-level pgd is changed... */ - if (mm == current->active_mm) - write_cr3(read_cr3()); + flush_tlb_mm(mm); } #else /* !CONFIG_X86_PAE */ -- cgit v1.2.3 From 5ac44fed9008dd82edb8bd3470698d8b83d2fed9 Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Tue, 15 Mar 2011 13:27:17 -0600 Subject: smp_call_function_many: handle concurrent clearing of mask commit 723aae25d5cdb09962901d36d526b44d4be1051c upstream. Mike Galbraith reported finding a lockup ("perma-spin bug") where the cpumask passed to smp_call_function_many was cleared by other cpu(s) while a cpu was preparing its call_data block, resulting in no cpu to clear the last ref and unlock the block. Having cpus clear their bit asynchronously could be useful on a mask of cpus that might have a translation context, or cpus that need a push to complete an rcu window. Instead of adding a BUG_ON and requiring yet another cpumask copy, just detect the race and handle it. Note: arch_send_call_function_ipi_mask must still handle an empty cpumask because the data block is globally visible before the that arch callback is made. And (obviously) there are no guarantees to which cpus are notified if the mask is changed during the call; only cpus that were online and had their mask bit set during the whole call are guaranteed to be called. Reported-by: Mike Galbraith Reported-by: Jan Beulich Acked-by: Jan Beulich Signed-off-by: Milton Miller Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/smp.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/kernel/smp.c b/kernel/smp.c index f697ca9ea975..b89ef31396c4 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -427,7 +427,7 @@ void smp_call_function_many(const struct cpumask *mask, { struct call_function_data *data; unsigned long flags; - int cpu, next_cpu, this_cpu = smp_processor_id(); + int refs, cpu, next_cpu, this_cpu = smp_processor_id(); /* * Can deadlock when called with interrupts disabled. @@ -438,7 +438,7 @@ void smp_call_function_many(const struct cpumask *mask, WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled() && !oops_in_progress); - /* So, what's a CPU they want? Ignoring this one. */ + /* Try to fastpath. So, what's a CPU they want? Ignoring this one. */ cpu = cpumask_first_and(mask, cpu_online_mask); if (cpu == this_cpu) cpu = cpumask_next_and(cpu, mask, cpu_online_mask); @@ -496,6 +496,13 @@ void smp_call_function_many(const struct cpumask *mask, /* We rely on the "and" being processed before the store */ cpumask_and(data->cpumask, mask, cpu_online_mask); cpumask_clear_cpu(this_cpu, data->cpumask); + refs = cpumask_weight(data->cpumask); + + /* Some callers race with other cpus changing the passed mask */ + if (unlikely(!refs)) { + csd_unlock(&data->csd); + return; + } raw_spin_lock_irqsave(&call_function.lock, flags); /* @@ -509,7 +516,7 @@ void smp_call_function_many(const struct cpumask *mask, * to the cpumask before this write to refs, which indicates * data is on the list and is ready to be processed. */ - atomic_set(&data->refs, cpumask_weight(data->cpumask)); + atomic_set(&data->refs, refs); raw_spin_unlock_irqrestore(&call_function.lock, flags); /* -- cgit v1.2.3 From dcb3d4d2505262133fc2fbb904aecd04a78cb0ae Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Feb 2011 19:28:01 +0100 Subject: fix per-cpu flag problem in the cpu affinity checkers commit 9804c9eaeacfe78651052c5ddff31099f60ef78c upstream. The CHECK_IRQ_PER_CPU is wrong, it should be checking irq_to_desc(irq)->status not just irq. Signed-off-by: Thomas Gleixner Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/parisc/kernel/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index efbcee5d2220..e13fc3f37787 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -117,7 +117,7 @@ int cpu_check_affinity(unsigned int irq, const struct cpumask *dest) int cpu_dest; /* timer and ipi have to always be received on all CPUs */ - if (CHECK_IRQ_PER_CPU(irq)) { + if (CHECK_IRQ_PER_CPU(irq_to_desc(irq)->status)) { /* Bad linux design decision. The mask has already * been set; we must reset it */ cpumask_setall(irq_desc[irq].affinity); -- cgit v1.2.3 From 60f5700d693e7a23352851aa1c77d1aad8f3d062 Mon Sep 17 00:00:00 2001 From: Roman Fietze Date: Sun, 20 Mar 2011 14:50:52 +0100 Subject: i2c: Fix typo in instantiating-devices document commit 6ced9e6b3901af4ab6ac0a11231402c888286ea6 upstream. The struct i2c_board_info member holding the name is "type", not "name". Signed-off-by: Roman Fietze Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- Documentation/i2c/instantiating-devices | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/i2c/instantiating-devices b/Documentation/i2c/instantiating-devices index e89490270aba..ed1779c55911 100644 --- a/Documentation/i2c/instantiating-devices +++ b/Documentation/i2c/instantiating-devices @@ -100,7 +100,7 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev) (...) i2c_adap = i2c_get_adapter(2); memset(&i2c_info, 0, sizeof(struct i2c_board_info)); - strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE); + strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE); isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info, normal_i2c); i2c_put_adapter(i2c_adap); -- cgit v1.2.3 From 5857fb84e4065b8e502f8eb1db4041aa69d51812 Mon Sep 17 00:00:00 2001 From: Stefan Nilsson XK Date: Tue, 1 Mar 2011 14:41:04 +0100 Subject: mmc: sdio: remember new card RCA when redetecting card commit 0aab3995485b8a994bf29a995a008c9ea4a28054 upstream. During redetection of a SDIO card, a request for a new card RCA was submitted to the card, but was then overwritten by the old RCA. This caused the card to be deselected instead of selected when using the incorrect RCA. This bug's been present since the "oldcard" handling was introduced in 2.6.32. Signed-off-by: Stefan Nilsson XK Signed-off-by: Andi Kleen Reviewed-by: Ulf Hansson Reviewed-by: Pawel Wieczorkiewicz Signed-off-by: Linus Walleij Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/core/sdio.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index b9dee28ee7d0..ac3f2c0c1c3e 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -309,6 +309,14 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, if (err) goto remove; + /* + * Update oldcard with the new RCA received from the SDIO + * device -- we're doing this so that it's updated in the + * "card" struct when oldcard overwrites that later. + */ + if (oldcard) + oldcard->rca = card->rca; + mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); } -- cgit v1.2.3 From ef8844ee3f2c657b1e5a92250721dc1c73c96c9a Mon Sep 17 00:00:00 2001 From: Alexander van Heukelum Date: Fri, 11 Mar 2011 21:59:38 +0100 Subject: x86, binutils, xen: Fix another wrong size directive commit 371c394af27ab7d1e58a66bc19d9f1f3ac1f67b4 upstream. The latest binutils (2.21.0.20110302/Ubuntu) breaks the build yet another time, under CONFIG_XEN=y due to a .size directive that refers to a slightly differently named (hence, to the now very strict and unforgiving assembler, non-existent) symbol. [ mingo: This unnecessary build breakage caused by new binutils version 2.21 gets escallated back several kernel releases spanning several years of Linux history, affecting over 130,000 upstream kernel commits (!), on CONFIG_XEN=y 64-bit kernels (i.e. essentially affecting all major Linux distro kernel configs). Git annotate tells us that this slight debug symbol code mismatch bug has been introduced in 2008 in commit 3d75e1b8: 3d75e1b8 (Jeremy Fitzhardinge 2008-07-08 15:06:49 -0700 1231) ENTRY(xen_do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs) The 'bug' is just a slight assymetry in ENTRY()/END() debug-symbols sequences, with lots of assembly code between the ENTRY() and the END(): ENTRY(xen_do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs) ... END(do_hypervisor_callback) Human reviewers almost never catch such small mismatches, and binutils never even warned about it either. This new binutils version thus breaks the Xen build on all upstream kernels since v2.6.27, out of the blue. This makes a straightforward Git bisection of all 64-bit Xen-enabled kernels impossible on such binutils, for a bisection window of over hundred thousand historic commits. (!) This is a major fail on the side of binutils and binutils needs to turn this show-stopper build failure into a warning ASAP. ] Signed-off-by: Alexander van Heukelum Signed-off-by: Andi Kleen Cc: Jeremy Fitzhardinge Cc: Jan Beulich Cc: H.J. Lu Cc: Linus Torvalds Cc: Andrew Morton Cc: "H. Peter Anvin" Cc: Kees Cook LKML-Reference: <1299877178-26063-1-git-send-email-heukelum@fastmail.fm> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/entry_64.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 4db7c4d12ffa..2642cf9911f8 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -1268,7 +1268,7 @@ ENTRY(xen_do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs) decl PER_CPU_VAR(irq_count) jmp error_exit CFI_ENDPROC -END(do_hypervisor_callback) +END(xen_do_hypervisor_callback) /* * Hypervisor uses this for application faults while it executes. -- cgit v1.2.3 From 4d5afe547f5edb659a7813d8190842da14618808 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Mon, 21 Mar 2011 17:59:35 +0100 Subject: hwmon: (sht15) Fix integer overflow in humidity calculation commit ccd32e735de7a941906e093f8dca924bb05c5794 upstream. An integer overflow occurs in the calculation of RHlinear when the relative humidity is greater than around 30%. The consequence is a subtle (but noticeable) error in the resulting humidity measurement. Signed-off-by: Vivien Didelot Signed-off-by: Jean Delvare Signed-off-by: Andi Kleen Cc: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/sht15.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c index a610e7880fb3..38a41d27f3da 100644 --- a/drivers/hwmon/sht15.c +++ b/drivers/hwmon/sht15.c @@ -333,11 +333,11 @@ static inline int sht15_calc_humid(struct sht15_data *data) const int c1 = -4; const int c2 = 40500; /* x 10 ^ -6 */ - const int c3 = -2800; /* x10 ^ -9 */ + const int c3 = -28; /* x 10 ^ -7 */ RHlinear = c1*1000 + c2 * data->val_humid/1000 - + (data->val_humid * data->val_humid * c3)/1000000; + + (data->val_humid * data->val_humid * c3) / 10000; return (temp - 25000) * (10000 + 80 * data->val_humid) / 1000000 + RHlinear; } -- cgit v1.2.3 From b9aa753f949640e886e776a793af042f4262bde7 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 22 Mar 2011 16:35:10 -0700 Subject: aio: wake all waiters when destroying ctx commit e91f90bb0bb10be9cc8efd09a3cf4ecffcad0db1 upstream. The test program below will hang because io_getevents() uses add_wait_queue_exclusive(), which means the wake_up() in io_destroy() only wakes up one of the threads. Fix this by using wake_up_all() in the aio code paths where we want to make sure no one gets stuck. // t.c -- compile with gcc -lpthread -laio t.c #include #include #include #include static const int nthr = 2; void *getev(void *ctx) { struct io_event ev; io_getevents(ctx, 1, 1, &ev, NULL); printf("io_getevents returned\n"); return NULL; } int main(int argc, char *argv[]) { io_context_t ctx = 0; pthread_t thread[nthr]; int i; io_setup(1024, &ctx); for (i = 0; i < nthr; ++i) pthread_create(&thread[i], NULL, getev, ctx); sleep(1); io_destroy(ctx); for (i = 0; i < nthr; ++i) pthread_join(thread[i], NULL); return 0; } Signed-off-by: Roland Dreier Signed-off-by: Andi Kleen Reviewed-by: Jeff Moyer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/aio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 5fb0fd7c80a0..a564a9d2727b 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -512,7 +512,7 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) ctx->reqs_active--; if (unlikely(!ctx->reqs_active && ctx->dead)) - wake_up(&ctx->wait); + wake_up_all(&ctx->wait); } static void aio_fput_routine(struct work_struct *data) @@ -1233,7 +1233,7 @@ static void io_destroy(struct kioctx *ioctx) * by other CPUs at this point. Right now, we rely on the * locking done by the above calls to ensure this consistency. */ - wake_up(&ioctx->wait); + wake_up_all(&ioctx->wait); put_ioctx(ioctx); /* once for the lookup */ } -- cgit v1.2.3 From b845a0bebf3e8728277ed92e1cb66e8901cf4b50 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Tue, 22 Mar 2011 16:33:43 -0700 Subject: shmem: let shared anonymous be nonlinear again commit bee4c36a5cf5c9f63ce1d7372aa62045fbd16d47 upstream. Up to 2.6.22, you could use remap_file_pages(2) on a tmpfs file or a shared mapping of /dev/zero or a shared anonymous mapping. In 2.6.23 we disabled it by default, but set VM_CAN_NONLINEAR to enable it on safe mappings. We made sure to set it in shmem_mmap() for tmpfs files, but missed it in shmem_zero_setup() for the others. Fix that at last. Reported-by: Kenny Simpson Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- mm/shmem.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/shmem.c b/mm/shmem.c index f65f84062db5..676eed337809 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2756,5 +2756,6 @@ int shmem_zero_setup(struct vm_area_struct *vma) fput(vma->vm_file); vma->vm_file = file; vma->vm_ops = &shmem_vm_ops; + vma->vm_flags |= VM_CAN_NONLINEAR; return 0; } -- cgit v1.2.3 From 5ccd2de34ed4817d5b1acaaddc2af5082885ea4f Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Mon, 28 Feb 2011 16:20:11 +0000 Subject: PCI hotplug: acpiphp: set current_state to D0 in register_slot commit 47e9037ac16637cd7f12b8790ea7ce6680e42168 upstream. If a device doesn't support power management (pm_cap == 0) but it is acpi_pci_power_manageable() because there is a _PS0 method declared for it and _EJ0 is also declared for the slot then nobody is going to set current_state = PCI_D0 for this device. This is what I think it is happening: pci_enable_device | __pci_enable_device_flags /* here we do not set current_state because !pm_cap */ | do_pci_enable_device | pci_set_power_state | __pci_start_power_transition | pci_platform_power_transition /* platform_pci_power_manageable() calls acpi_pci_power_manageable that * returns true */ | platform_pci_set_power_state /* acpi_pci_set_power_state gets called and does nothing because the * acpi device has _EJ0, see the comment "If the ACPI device has _EJ0, * ignore the device" */ at this point if we refer to the commit message that introduced the comment above (10b3dcae0f275e2546e55303d64ddbb58cec7599), it is up to the hotplug driver to set the state to D0. However AFAICT the pci hotplug driver never does, in fact drivers/pci/hotplug/acpiphp_glue.c:register_slot sets the slot flags to (SLOT_ENABLED | SLOT_POWEREDON) but it does not set the pci device current state to PCI_D0. So my proposed fix is also to set current_state = PCI_D0 in register_slot. Comments are very welcome. Signed-off-by: Stefano Stabellini Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/pci/hotplug/acpiphp_glue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index cb23aa2ebf96..e610cfe4f07b 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -212,6 +212,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) pdev = pci_get_slot(pbus, PCI_DEVFN(device, function)); if (pdev) { + pdev->current_state = PCI_D0; slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); pci_dev_put(pdev); } -- cgit v1.2.3 From c358c7982e8c4c5f1012a76fc3045eee29bb6824 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Fri, 18 Feb 2011 11:32:40 +0000 Subject: xen: set max_pfn_mapped to the last pfn mapped commit 14988a4d350ce3b41ecad4f63c4f44c56f5ae34d upstream. Do not set max_pfn_mapped to the end of the initial memory mappings, that also contain pages that don't belong in pfn space (like the mfn list). Set max_pfn_mapped to the last real pfn mapped in the initial memory mappings that is the pfn backing _end. Signed-off-by: Stefano Stabellini Acked-by: Konrad Rzeszutek Wilk Signed-off-by: Andi Kleen LKML-Reference: Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/mmu.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 914f04695ce5..6adff931d5f3 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1641,9 +1641,6 @@ static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) for (pteidx = 0; pteidx < PTRS_PER_PTE; pteidx++, pfn++) { pte_t pte; - if (pfn > max_pfn_mapped) - max_pfn_mapped = pfn; - if (!pte_none(pte_page[pteidx])) continue; @@ -1687,6 +1684,12 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, pud_t *l3; pmd_t *l2; + /* max_pfn_mapped is the last pfn mapped in the initial memory + * mappings. Considering that on Xen after the kernel mappings we + * have the mappings of some pages that don't exist in pfn space, we + * set max_pfn_mapped to the last real pfn mapped. */ + max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list)); + /* Zap identity mapping */ init_level4_pgt[0] = __pgd(0); @@ -1750,9 +1753,7 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, { pmd_t *kernel_pmd; - max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) + - xen_start_info->nr_pt_frames * PAGE_SIZE + - 512*1024); + max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list)); kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd); memcpy(level2_kernel_pgt, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD); -- cgit v1.2.3 From 4f34c6e9301963bb8e6d9ad47226ece6bd8e6677 Mon Sep 17 00:00:00 2001 From: Julien Tinnes Date: Fri, 18 Mar 2011 15:05:21 -0700 Subject: Prevent rt_sigqueueinfo and rt_tgsigqueueinfo from spoofing the signal code commit da48524eb20662618854bb3df2db01fc65f3070c upstream. Userland should be able to trust the pid and uid of the sender of a signal if the si_code is SI_TKILL. Unfortunately, the kernel has historically allowed sigqueueinfo() to send any si_code at all (as long as it was negative - to distinguish it from kernel-generated signals like SIGILL etc), so it could spoof a SI_TKILL with incorrect siginfo values. Happily, it looks like glibc has always set si_code to the appropriate SI_QUEUE, so there are probably no actual user code that ever uses anything but the appropriate SI_QUEUE flag. So just tighten the check for si_code (we used to allow any negative value), and add a (one-time) warning in case there are binaries out there that might depend on using other si_code values. Signed-off-by: Julien Tinnes Acked-by: Oleg Nesterov Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/signal.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/kernel/signal.c b/kernel/signal.c index bded65187780..cb0fff39f4e8 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2410,9 +2410,13 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig, return -EFAULT; /* Not even root can pretend to send signals from the kernel. - Nor can they impersonate a kill(), which adds source info. */ - if (info.si_code >= 0) + * Nor can they impersonate a kill()/tgkill(), which adds source info. + */ + if (info.si_code != SI_QUEUE) { + /* We used to allow any < 0 si_code */ + WARN_ON_ONCE(info.si_code < 0); return -EPERM; + } info.si_signo = sig; /* POSIX.1b doesn't mention process groups. */ @@ -2426,9 +2430,13 @@ long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info) return -EINVAL; /* Not even root can pretend to send signals from the kernel. - Nor can they impersonate a kill(), which adds source info. */ - if (info->si_code >= 0) + * Nor can they impersonate a kill()/tgkill(), which adds source info. + */ + if (info->si_code != SI_QUEUE) { + /* We used to allow any < 0 si_code */ + WARN_ON_ONCE(info->si_code < 0); return -EPERM; + } info->si_signo = sig; return do_send_specific(tgid, pid, sig, info); -- cgit v1.2.3 From 24ce42c3962c4e15b96ae6d1ccd9d558848eec75 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Sat, 26 Feb 2011 22:40:19 +0200 Subject: ext3: skip orphan cleanup on rocompat fs commit ce654b37f87980d95f339080e4c3bdb2370bdf22 upstream. Orphan cleanup is currently executed even if the file system has some number of unknown ROCOMPAT features, which deletes inodes and frees blocks, which could be very bad for some RO_COMPAT features. This patch skips the orphan cleanup if it contains readonly compatible features not known by this ext3 implementation, which would prevent the fs from being mounted (or remounted) readwrite. Signed-off-by: Amir Goldstein Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ext3/super.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 6c953bb255e7..6c7efb689062 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -1459,6 +1459,13 @@ static void ext3_orphan_cleanup (struct super_block * sb, return; } + /* Check if feature set allows readwrite operations */ + if (EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP)) { + printk(KERN_INFO "EXT3-fs: %s: Skipping orphan cleanup due to " + "unknown ROCOMPAT features\n", sb->s_id); + return; + } + if (EXT3_SB(sb)->s_mount_state & EXT3_ERROR_FS) { if (es->s_last_orphan) jbd_debug(1, "Errors on filesystem, " -- cgit v1.2.3 From 0b5d79b55f305d2d9c00f4760b0653f40187be4e Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 23 Mar 2011 16:42:50 -0700 Subject: procfs: fix /proc//maps heap check commit 0db0c01b53a1a421513f91573241aabafb87802a upstream. The current code fails to print the "[heap]" marking if the heap is split into multiple mappings. Fix the check so that the marking is displayed in all possible cases: 1. vma matches exactly the heap 2. the heap vma is merged e.g. with bss 3. the heap vma is splitted e.g. due to locked pages Test cases. In all cases, the process should have mapping(s) with [heap] marking: (1) vma matches exactly the heap #include #include #include int main (void) { if (sbrk(4096) != (void *)-1) { printf("check /proc/%d/maps\n", (int)getpid()); while (1) sleep(1); } return 0; } # ./test1 check /proc/553/maps [1] + Stopped ./test1 # cat /proc/553/maps | head -4 00008000-00009000 r-xp 00000000 01:00 3113640 /test1 00010000-00011000 rw-p 00000000 01:00 3113640 /test1 00011000-00012000 rw-p 00000000 00:00 0 [heap] 4006f000-40070000 rw-p 00000000 00:00 0 (2) the heap vma is merged #include #include #include char foo[4096] = "foo"; char bar[4096]; int main (void) { if (sbrk(4096) != (void *)-1) { printf("check /proc/%d/maps\n", (int)getpid()); while (1) sleep(1); } return 0; } # ./test2 check /proc/556/maps [2] + Stopped ./test2 # cat /proc/556/maps | head -4 00008000-00009000 r-xp 00000000 01:00 3116312 /test2 00010000-00012000 rw-p 00000000 01:00 3116312 /test2 00012000-00014000 rw-p 00000000 00:00 0 [heap] 4004a000-4004b000 rw-p 00000000 00:00 0 (3) the heap vma is splitted (this fails without the patch) #include #include #include #include int main (void) { if ((sbrk(4096) != (void *)-1) && !mlockall(MCL_FUTURE) && (sbrk(4096) != (void *)-1)) { printf("check /proc/%d/maps\n", (int)getpid()); while (1) sleep(1); } return 0; } # ./test3 check /proc/559/maps [1] + Stopped ./test3 # cat /proc/559/maps|head -4 00008000-00009000 r-xp 00000000 01:00 3119108 /test3 00010000-00011000 rw-p 00000000 01:00 3119108 /test3 00011000-00012000 rw-p 00000000 00:00 0 [heap] 00012000-00013000 rw-p 00000000 00:00 0 [heap] It looks like the bug has been there forever, and since it only results in some information missing from a procfile, it does not fulfil the -stable "critical issue" criteria. Signed-off-by: Aaro Koskinen Signed-off-by: Andi Kleen Reviewed-by: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/proc/task_mmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 271afc48b9a5..0dfd815e4cfd 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -248,8 +248,8 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) const char *name = arch_vma_name(vma); if (!name) { if (mm) { - if (vma->vm_start <= mm->start_brk && - vma->vm_end >= mm->brk) { + if (vma->vm_start <= mm->brk && + vma->vm_end >= mm->start_brk) { name = "[heap]"; } else if (vma->vm_start <= mm->start_stack && vma->vm_end >= mm->start_stack) { -- cgit v1.2.3 From 9496d25a15f0cb376a2d7a22f27ad372f6dfca44 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 23 Mar 2011 16:42:53 -0700 Subject: proc: protect mm start_code/end_code in /proc/pid/stat commit 5883f57ca0008ffc93e09cbb9847a1928e50c6f3 upstream. While mm->start_stack was protected from cross-uid viewing (commit f83ce3e6b02d5 ("proc: avoid information leaks to non-privileged processes")), the start_code and end_code values were not. This would allow the text location of a PIE binary to leak, defeating ASLR. Note that the value "1" is used instead of "0" for a protected value since "ps", "killall", and likely other readers of /proc/pid/stat, take start_code of "0" to mean a kernel thread and will misbehave. Thanks to Brad Spengler for pointing this out. Addresses CVE-2011-0726 Signed-off-by: Kees Cook Signed-off-by: Andi Kleen Cc: Alexey Dobriyan Cc: David Howells Cc: Eugene Teo Cc: Martin Schwidefsky Cc: Brad Spengler Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/proc/array.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/proc/array.c b/fs/proc/array.c index 3d88fe1b9843..9e5f43084912 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -489,8 +489,8 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, vsize, mm ? get_mm_rss(mm) : 0, rsslim, - mm ? mm->start_code : 0, - mm ? mm->end_code : 0, + mm ? (permitted ? mm->start_code : 1) : 0, + mm ? (permitted ? mm->end_code : 1) : 0, (permitted && mm) ? mm->start_stack : 0, esp, eip, -- cgit v1.2.3 From c704af98055ff4b3280c5ee59a7badf27a6f7e1a Mon Sep 17 00:00:00 2001 From: Henry Nestler Date: Sun, 20 Feb 2011 20:50:56 +0000 Subject: fbcon: Bugfix soft cursor detection in Tile Blitting commit d6244bc0ed0c52a795e6f4dcab3886daf3e74fac upstream. Use mask 0x10 for "soft cursor" detection on in function tile_cursor. (Tile Blitting Operation in framebuffer console). The old mask 0x01 for vc_cursor_type detects CUR_NONE, CUR_LOWER_THIRD and every second mode value as "software cursor". This hides the cursor for these modes (cursor.mode = 0). But, only CUR_NONE or "software cursor" should hide the cursor. See also 0x10 in functions add_softcursor, bit_cursor and cw_cursor. Signed-off-by: Henry Nestler Signed-off-by: Paul Mundt Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/video/console/tileblit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c index 0056a41e5c35..15e8e1a89c45 100644 --- a/drivers/video/console/tileblit.c +++ b/drivers/video/console/tileblit.c @@ -83,7 +83,7 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode, int softback_lines, int fg, int bg) { struct fb_tilecursor cursor; - int use_sw = (vc->vc_cursor_type & 0x01); + int use_sw = (vc->vc_cursor_type & 0x10); cursor.sx = vc->vc_x; cursor.sy = vc->vc_y; -- cgit v1.2.3 From 6d3760c3a4c60286f5c564b2fb9247324205ce72 Mon Sep 17 00:00:00 2001 From: Mi Jinlong Date: Fri, 18 Feb 2011 09:08:31 +0800 Subject: nfsd41: modify the members value of nfsd4_op_flags commit 5ece3cafbd88d4da5c734e1810c4a2e6474b57b2 upstream. The members of nfsd4_op_flags, (ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS) equals to ALLOWED_AS_FIRST_OP, maybe that's not what we want. OP_PUTROOTFH with op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, can't appears as the first operation with out SEQUENCE ops. This patch modify the wrong value of ALLOWED_WITHOUT_FH etc which was introduced by f9bb94c4. Reviewed-by: Benny Halevy Signed-off-by: Mi Jinlong Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfsd/nfs4proc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 59ec449b0c7f..bb775a595989 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -954,8 +954,8 @@ typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *, void *); enum nfsd4_op_flags { ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */ - ALLOWED_ON_ABSENT_FS = 2 << 0, /* ops processed on absent fs */ - ALLOWED_AS_FIRST_OP = 3 << 0, /* ops reqired first in compound */ + ALLOWED_ON_ABSENT_FS = 1 << 1, /* ops processed on absent fs */ + ALLOWED_AS_FIRST_OP = 1 << 2, /* ops reqired first in compound */ }; struct nfsd4_operation { -- cgit v1.2.3 From c3b31b69a2264c21bb2da19ff1df5a04fe024bd9 Mon Sep 17 00:00:00 2001 From: Stephan Lachowsky Date: Thu, 27 Jan 2011 23:04:33 -0300 Subject: uvcvideo: Fix uvc_fixup_video_ctrl() format search commit 38a66824d96de8aeeb915e6f46f0d3fe55828eb1 upstream. The scheme used to index format in uvc_fixup_video_ctrl() is not robust: format index is based on descriptor ordering, which does not necessarily match bFormatIndex ordering. Searching for first matching format will prevent uvc_fixup_video_ctrl() from using the wrong format/frame to make adjustments. Signed-off-by: Stephan Lachowsky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/media/video/uvc/uvc_video.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 53f3ef4635eb..4b0870cc1e69 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -65,15 +65,19 @@ int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, struct uvc_streaming_control *ctrl) { - struct uvc_format *format; + struct uvc_format *format = NULL; struct uvc_frame *frame = NULL; unsigned int i; - if (ctrl->bFormatIndex <= 0 || - ctrl->bFormatIndex > stream->nformats) - return; + for (i = 0; i < stream->nformats; ++i) { + if (stream->format[i].index == ctrl->bFormatIndex) { + format = &stream->format[i]; + break; + } + } - format = &stream->format[ctrl->bFormatIndex - 1]; + if (format == NULL) + return; for (i = 0; i < format->nframes; ++i) { if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) { -- cgit v1.2.3 From 83ed3460b8ab1880f670dbf925f50bb7e156346f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 16 Mar 2011 10:57:15 -0400 Subject: ehci-hcd: Bug fix: don't set a QH's Halt bit commit b5a3b3d985493c173925907adfebf3edab236fe7 upstream. This patch (as1453) fixes a long-standing bug in the ehci-hcd driver. There is no need to set the Halt bit in the overlay region for an unlinked or blocked QH. Contrary to what the comment says, setting the Halt bit does not cause the QH to be patched later; that decision (made in qh_refresh()) depends only on whether the QH is currently pointing to a valid qTD. Likewise, setting the Halt bit does not prevent completions from activating the QH while it is "stopped"; they are prevented by the fact that qh_completions() temporarily changes qh->qh_state to QH_STATE_COMPLETING. On the other hand, there are circumstances in which the QH will be reactivated _without_ being patched; this happens after an URB beyond the head of the queue is unlinked. Setting the Halt bit will then cause the hardware to see the QH with both the Active and Halt bits set, an invalid combination that will prevent the queue from advancing and may even crash some controllers. Apparently the only reason this hasn't been reported before is that unlinking URBs from the middle of a running queue is quite uncommon. However Test 17, recently added to the usbtest driver, does exactly this, and it confirms the presence of the bug. In short, there is no reason to set the Halt bit for an unlinked or blocked QH, and there is a very good reason not to set it. Therefore the code that sets it is removed. Signed-off-by: Alan Stern Tested-by: Andiry Xu CC: David Brownell Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/ehci-q.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 11a79c4f4a9d..98f022d2947f 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -315,7 +315,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) int stopped; unsigned count = 0; u8 state; - const __le32 halt = HALT_BIT(ehci); struct ehci_qh_hw *hw = qh->hw; if (unlikely (list_empty (&qh->qtd_list))) @@ -422,7 +421,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) && !(qtd->hw_alt_next & EHCI_LIST_END(ehci))) { stopped = 1; - goto halt; } /* stop scanning when we reach qtds the hc is using */ @@ -456,16 +454,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) */ ehci_clear_tt_buffer(ehci, qh, urb, token); } - - /* force halt for unlinked or blocked qh, so we'll - * patch the qh later and so that completions can't - * activate it while we "know" it's stopped. - */ - if ((halt & hw->hw_token) == 0) { -halt: - hw->hw_token |= halt; - wmb (); - } } /* unless we already know the urb's status, collect qtd status -- cgit v1.2.3 From a0a81bea48c2dfebd7cd557d52788198d1f42d07 Mon Sep 17 00:00:00 2001 From: Peter Holik Date: Fri, 18 Mar 2011 18:47:44 +0100 Subject: USB: uss720 fixup refcount position commit adaa3c6342b249548ea830fe8e02aa5b45be8688 upstream. My testprog do a lot of bitbang - after hours i got following warning and my machine lockups: WARNING: at /build/buildd/linux-2.6.38/lib/kref.c:34 After debugging uss720 driver i discovered that the completion callback was called before usb_submit_urb returns. The callback frees the request structure that is krefed on return by usb_submit_urb. Signed-off-by: Peter Holik Acked-by: Thomas Sailer Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/misc/uss720.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 4ff21587ab03..9727daa1cc72 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -177,12 +177,11 @@ static struct uss720_async_request *submit_async_request(struct parport_uss720_p spin_lock_irqsave(&priv->asynclock, flags); list_add_tail(&rq->asynclist, &priv->asynclist); spin_unlock_irqrestore(&priv->asynclock, flags); + kref_get(&rq->ref_count); ret = usb_submit_urb(rq->urb, mem_flags); - if (!ret) { - kref_get(&rq->ref_count); + if (!ret) return rq; - } - kref_put(&rq->ref_count, destroy_async); + destroy_async(&rq->ref_count); err("submit_async_request submit_urb failed with %d", ret); return NULL; } -- cgit v1.2.3 From 6fff16ce9d1cf7aa4dc2b07410e338e04bc47582 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Mar 2011 11:12:09 +0100 Subject: USB: cdc-acm: fix memory corruption / panic commit 23b80550e2aa61d0ba3af98b831b9195be0db9ee upstream. Prevent read urbs from being resubmitted from tasklet after port close. The receive tasklet was not disabled on port close, which could lead to corruption of receive lists on consecutive port open. In particular, read urbs could be re-submitted before port open, added to free list in open, and then added a second time to the free list in the completion handler. cdc-acm.c: Entering acm_tty_open. cdc-acm.c: acm_control_msg: rq: 0x22 val: 0x3 len: 0x0 result: 0 cdc-acm.c: Entering acm_rx_tasklet cdc-acm.c: acm_rx_tasklet: sending urb 0xf50da280, rcv 0xf57fbc24, buf 0xf57fbd64 cdc-acm.c: set line: 115200 0 0 8 cdc-acm.c: acm_control_msg: rq: 0x20 val: 0x0 len: 0x7 result: 7 cdc-acm.c: acm_tty_close cdc-acm.c: acm_port_down cdc-acm.c: acm_control_msg: rq: 0x22 val: 0x0 len: 0x0 result: 0 cdc-acm.c: acm_ctrl_irq - urb shutting down with status: -2 cdc-acm.c: acm_rx_tasklet: sending urb 0xf50da300, rcv 0xf57fbc10, buf 0xf57fbd50 cdc-acm.c: Entering acm_read_bulk with status -2 cdc_acm 4-1:1.1: Aborting, acm not ready cdc-acm.c: Entering acm_read_bulk with status -2 cdc_acm 4-1:1.1: Aborting, acm not ready cdc-acm.c: acm_rx_tasklet: sending urb 0xf50da380, rcv 0xf57fbbfc, buf 0xf57fbd3c cdc-acm.c: acm_rx_tasklet: sending urb 0xf50da400, rcv 0xf57fbbe8, buf 0xf57fbd28 cdc-acm.c: acm_rx_tasklet: sending urb 0xf50da480, rcv 0xf57fbbd4, buf 0xf57fbd14 cdc-acm.c: acm_rx_tasklet: sending urb 0xf50da900, rcv 0xf57fbbc0, buf 0xf57fbd00 cdc-acm.c: acm_rx_tasklet: sending urb 0xf50da980, rcv 0xf57fbbac, buf 0xf57fbcec cdc-acm.c: acm_rx_tasklet: sending urb 0xf50daa00, rcv 0xf57fbb98, buf 0xf57fbcd8 cdc-acm.c: acm_rx_tasklet: sending urb 0xf50daa80, rcv 0xf57fbb84, buf 0xf57fbcc4 cdc-acm.c: acm_rx_tasklet: sending urb 0xf50dab00, rcv 0xf57fbb70, buf 0xf57fbcb0 cdc-acm.c: acm_rx_tasklet: sending urb 0xf50dab80, rcv 0xf57fbb5c, buf 0xf57fbc9c cdc-acm.c: acm_rx_tasklet: sending urb 0xf50dac00, rcv 0xf57fbb48, buf 0xf57fbc88 cdc-acm.c: acm_rx_tasklet: sending urb 0xf50dac80, rcv 0xf57fbb34, buf 0xf57fbc74 cdc-acm.c: acm_rx_tasklet: sending urb 0xf50dad00, rcv 0xf57fbb20, buf 0xf57fbc60 cdc-acm.c: acm_rx_tasklet: sending urb 0xf50dad80, rcv 0xf57fbb0c, buf 0xf57fbc4c cdc-acm.c: acm_rx_tasklet: sending urb 0xf50da880, rcv 0xf57fbaf8, buf 0xf57fbc38 cdc-acm.c: Entering acm_tty_open. cdc-acm.c: acm_control_msg: rq: 0x22 val: 0x3 len: 0x0 result: 0 cdc-acm.c: Entering acm_rx_tasklet cdc-acm.c: acm_rx_tasklet: sending urb 0xf50da280, rcv 0xf57fbc24, buf 0xf57fbd64 cdc-acm.c: Entering acm_tty_write to write 3 bytes, cdc-acm.c: Get 3 bytes... cdc-acm.c: acm_write_start susp_count: 0 cdc-acm.c: Entering acm_read_bulk with status 0 Signed-off-by: Andi Kleen ------------[ cut here ]------------ WARNING: at /home/johan/src/linux/linux-2.6/lib/list_debug.c:57 list_del+0x10c/0x120() Hardware name: Vostro 1520 list_del corruption. next->prev should be f57fbc10, but was f57fbaf8 Modules linked in: cdc_acm Pid: 3, comm: ksoftirqd/0 Not tainted 2.6.37+ #39 Call Trace: [] warn_slowpath_common+0x72/0xa0 [] ? list_del+0x10c/0x120 [] ? list_del+0x10c/0x120 [] warn_slowpath_fmt+0x33/0x40 [] list_del+0x10c/0x120 [] acm_rx_tasklet+0xef/0x3e0 [cdc_acm] [] ? net_rps_action_and_irq_enable+0x6d/0x80 [] tasklet_action+0xe6/0x140 [] __do_softirq+0xaf/0x210 [] ? __do_softirq+0x0/0x210 [] ? run_ksoftirqd+0x8a/0x1c0 [] ? run_ksoftirqd+0x0/0x1c0 [] ? kthread+0x74/0x80 [] ? kthread+0x0/0x80 [] ? kernel_thread_helper+0x6/0x10 ---[ end trace efd9a11434f0082e ]--- ------------[ cut here ]------------ WARNING: at /home/johan/src/linux/linux-2.6/lib/list_debug.c:57 list_del+0x10c/0x120() Hardware name: Vostro 1520 list_del corruption. next->prev should be f57fbd50, but was f57fbdb0 Modules linked in: cdc_acm Pid: 3, comm: ksoftirqd/0 Tainted: G W 2.6.37+ #39 Call Trace: [] warn_slowpath_common+0x72/0xa0 [] ? list_del+0x10c/0x120 [] ? list_del+0x10c/0x120 [] warn_slowpath_fmt+0x33/0x40 [] list_del+0x10c/0x120 [] acm_rx_tasklet+0x106/0x3e0 [cdc_acm] [] ? net_rps_action_and_irq_enable+0x6d/0x80 [] tasklet_action+0xe6/0x140 [] __do_softirq+0xaf/0x210 [] ? __do_softirq+0x0/0x210 [] ? run_ksoftirqd+0x8a/0x1c0 [] ? run_ksoftirqd+0x0/0x1c0 [] ? kthread+0x74/0x80 [] ? kthread+0x0/0x80 [] ? kernel_thread_helper+0x6/0x10 ---[ end trace efd9a11434f0082f ]--- cdc-acm.c: acm_rx_tasklet: sending urb 0xf50da300, rcv 0xf57fbc10, buf 0xf57fbd50 cdc-acm.c: disconnected from network cdc-acm.c: acm_rx_tasklet: sending urb 0xf50da380, rcv 0xf57fbbfc, buf 0xf57fbd3c cdc-acm.c: Entering acm_rx_tasklet ------------[ cut here ]------------ WARNING: at /home/johan/src/linux/linux-2.6/lib/list_debug.c:48 list_del+0xd5/0x120() Hardware name: Vostro 1520 list_del corruption, next is LIST_POISON1 (00100100) Modules linked in: cdc_acm Pid: 3, comm: ksoftirqd/0 Tainted: G W 2.6.37+ #39 Call Trace: [] warn_slowpath_common+0x72/0xa0 [] ? list_del+0xd5/0x120 [] ? list_del+0xd5/0x120 [] warn_slowpath_fmt+0x33/0x40 [] list_del+0xd5/0x120 [] acm_rx_tasklet+0x2dc/0x3e0 [cdc_acm] [] ? trace_hardirqs_on+0xb/0x10 [] ? tasklet_action+0x60/0x140 [] tasklet_action+0xe6/0x140 [] __do_softirq+0xaf/0x210 [] ? __do_softirq+0x0/0x210 [] ? run_ksoftirqd+0x8a/0x1c0 [] ? run_ksoftirqd+0x0/0x1c0 [] ? kthread+0x74/0x80 [] ? kthread+0x0/0x80 [] ? kernel_thread_helper+0x6/0x10 ---[ end trace efd9a11434f00830 ]--- BUG: unable to handle kernel paging request at 00200200 IP: [] list_del+0x1d/0x120 *pde = 00000000 Oops: 0000 [#1] PREEMPT SMP last sysfs file: /sys/devices/pci0000:00/0000:00:1a.1/usb4/4-1/4-1:1.0/tty/ttyACM0/uevent Modules linked in: cdc_acm Pid: 3, comm: ksoftirqd/0 Tainted: G W 2.6.37+ #39 0T816J/Vostro 1520 EIP: 0060:[] EFLAGS: 00010046 CPU: 0 EIP is at list_del+0x1d/0x120 EAX: f57fbd3c EBX: f57fb800 ECX: ffff8000 EDX: 00200200 ESI: f57fbe90 EDI: f57fbd3c EBP: f600bf54 ESP: f600bf3c DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 Process ksoftirqd/0 (pid: 3, ti=f600a000 task=f60791c0 task.ti=f6082000) Stack: c1527e84 00000030 c1527e54 00100100 f57fb800 f57fbd3c f600bf98 f8051fac f8053104 f8052b94 f600bf6c c106dbab f600bf80 00000286 f60791c0 c1042b30 f57fbda8 f57f5800 f57fbdb0 f57fbd80 f57fbe7c c1656b04 00000000 f600bfb0 Call Trace: [] ? acm_rx_tasklet+0x2dc/0x3e0 [cdc_acm] [] ? trace_hardirqs_on+0xb/0x10 [] ? tasklet_action+0x60/0x140 [] ? tasklet_action+0xe6/0x140 [] ? __do_softirq+0xaf/0x210 [] ? __do_softirq+0x0/0x210 [] ? run_ksoftirqd+0x8a/0x1c0 [] ? run_ksoftirqd+0x0/0x1c0 [] ? kthread+0x74/0x80 [] ? kthread+0x0/0x80 [] ? kernel_thread_helper+0x6/0x10 Code: ff 48 14 e9 57 ff ff ff 90 90 90 90 90 90 55 89 e5 83 ec 18 81 38 00 01 10 00 0f 84 9c 00 00 00 8b 50 04 81 fa 00 02 20 00 74 33 <8b> 12 39 d0 75 5c 8b 10 8b 4a 04 39 c8 0f 85 b5 00 00 00 8b 48 EIP: [] list_del+0x1d/0x120 SS:ESP 0068:f600bf3c CR2: 0000000000200200 ---[ end trace efd9a11434f00831 ]--- Kernel panic - not syncing: Fatal exception in interrupt Pid: 3, comm: ksoftirqd/0 Tainted: G D W 2.6.37+ #39 Call Trace: [] ? printk+0x1d/0x24 [] panic+0x66/0x15c [] oops_end+0x8f/0x90 [] no_context+0xc6/0x160 [] __bad_area_nosemaphore+0x98/0x140 [] ? release_console_sem+0x1d8/0x210 [] bad_area_nosemaphore+0x17/0x20 [] do_page_fault+0x279/0x420 [] ? show_trace+0x1f/0x30 [] ? printk+0x1d/0x24 [] ? do_page_fault+0x0/0x420 [] error_code+0x5f/0x64 [] ? select_task_rq_fair+0x37b/0x6a0 [] ? do_page_fault+0x0/0x420 [] ? list_del+0x1d/0x120 [] acm_rx_tasklet+0x2dc/0x3e0 [cdc_acm] [] ? trace_hardirqs_on+0xb/0x10 [] ? tasklet_action+0x60/0x140 [] tasklet_action+0xe6/0x140 [] __do_softirq+0xaf/0x210 [] ? __do_softirq+0x0/0x210 [] ? run_ksoftirqd+0x8a/0x1c0 [] ? run_ksoftirqd+0x0/0x1c0 [] ? kthread+0x74/0x80 [] ? kthread+0x0/0x80 [] ? kernel_thread_helper+0x6/0x10 panic occurred, switching back to text console ------------[ cut here ]------------ Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 01b74aa37ea8..96500e90de3c 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -652,8 +652,10 @@ static void acm_port_down(struct acm *acm, int drain) usb_kill_urb(acm->ctrlurb); for (i = 0; i < ACM_NW; i++) usb_kill_urb(acm->wb[i].urb); + tasklet_disable(&acm->urb_task); for (i = 0; i < nr; i++) usb_kill_urb(acm->ru[i].urb); + tasklet_enable(&acm->urb_task); acm->control->needs_remote_wakeup = 0; usb_autopm_put_interface(acm->control); } -- cgit v1.2.3 From decdbcebb0bbb9b05858086131afc69b8a8da01e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Mar 2011 11:12:10 +0100 Subject: USB: cdc-acm: fix potential null-pointer dereference commit 15e5bee33ffc11d0e5c6f819a65e7881c5c407be upstream. Must check return value of tty_port_tty_get. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/class/cdc-acm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 96500e90de3c..3db3eaa11c1a 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -533,6 +533,8 @@ static void acm_softint(struct work_struct *work) if (!ACM_READY(acm)) return; tty = tty_port_tty_get(&acm->port); + if (!tty) + return; tty_wakeup(tty); tty_kref_put(tty); } -- cgit v1.2.3 From 6526452b56265b15e331004e3f3cc7f271bd4cd0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Mar 2011 11:12:11 +0100 Subject: USB: cdc-acm: fix potential null-pointer dereference on disconnect commit 7e7797e7f6f7bfab73fca02c65e40eaa5bb9000c upstream. Fix potential null-pointer exception on disconnect introduced by commit 11ea859d64b69a747d6b060b9ed1520eab1161fe (USB: additional power savings for cdc-acm devices that support remote wakeup). Only access acm->dev after making sure it is non-null in control urb completion handler. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/class/cdc-acm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 3db3eaa11c1a..2c70e1e6aa93 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -297,6 +297,8 @@ static void acm_ctrl_irq(struct urb *urb) if (!ACM_READY(acm)) goto exit; + usb_mark_last_busy(acm->dev); + data = (unsigned char *)(dr + 1); switch (dr->bNotificationType) { case USB_CDC_NOTIFY_NETWORK_CONNECTION: @@ -336,7 +338,6 @@ static void acm_ctrl_irq(struct urb *urb) break; } exit: - usb_mark_last_busy(acm->dev); retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with " -- cgit v1.2.3 From b88505e58ce6d36732cd15841cc821f97efca9bb Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Wed, 16 Mar 2011 22:11:46 -0700 Subject: Input: xen-kbdfront - advertise either absolute or relative coordinates commit 8c3c283e6bf463ab498d6e7823aff6c4762314b6 upstream. A virtualized display device is usually viewed with the vncviewer application, either by 'xm vnc domU' or with vncviewer localhost:port. vncviewer and the RFB protocol provides absolute coordinates to the virtual display. These coordinates are either passed through to a PV guest or converted to relative coordinates for a HVM guest. A PV guest receives these coordinates and passes them to the kernels evdev driver. There it can be picked up by applications such as the xorg-input drivers. Using absolute coordinates avoids issues such as guest mouse pointer not tracking host mouse pointer due to wrong mouse acceleration settings in the guests X display. Advertise either absolute or relative coordinates to the input system and the evdev driver, depending on what dom0 provides. The xorg-input driver prefers relative coordinates even if a devices provides both. Signed-off-by: Olaf Hering Signed-off-by: Stefano Stabellini Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/input/xen-kbdfront.c | 45 +++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c index e14081675bb2..6ad8be171d70 100644 --- a/drivers/input/xen-kbdfront.c +++ b/drivers/input/xen-kbdfront.c @@ -109,7 +109,7 @@ static irqreturn_t input_handler(int rq, void *dev_id) static int __devinit xenkbd_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { - int ret, i; + int ret, i, abs; struct xenkbd_info *info; struct input_dev *kbd, *ptr; @@ -127,6 +127,11 @@ static int __devinit xenkbd_probe(struct xenbus_device *dev, if (!info->page) goto error_nomem; + if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-abs-pointer", "%d", &abs) < 0) + abs = 0; + if (abs) + xenbus_printf(XBT_NIL, dev->nodename, "request-abs-pointer", "1"); + /* keyboard */ kbd = input_allocate_device(); if (!kbd) @@ -136,11 +141,12 @@ static int __devinit xenkbd_probe(struct xenbus_device *dev, kbd->id.bustype = BUS_PCI; kbd->id.vendor = 0x5853; kbd->id.product = 0xffff; - kbd->evbit[0] = BIT(EV_KEY); + + __set_bit(EV_KEY, kbd->evbit); for (i = KEY_ESC; i < KEY_UNKNOWN; i++) - set_bit(i, kbd->keybit); + __set_bit(i, kbd->keybit); for (i = KEY_OK; i < KEY_MAX; i++) - set_bit(i, kbd->keybit); + __set_bit(i, kbd->keybit); ret = input_register_device(kbd); if (ret) { @@ -159,12 +165,20 @@ static int __devinit xenkbd_probe(struct xenbus_device *dev, ptr->id.bustype = BUS_PCI; ptr->id.vendor = 0x5853; ptr->id.product = 0xfffe; - ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS); + + if (abs) { + __set_bit(EV_ABS, ptr->evbit); + input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0); + input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0); + } else { + input_set_capability(ptr, EV_REL, REL_X); + input_set_capability(ptr, EV_REL, REL_Y); + } + input_set_capability(ptr, EV_REL, REL_WHEEL); + + __set_bit(EV_KEY, ptr->evbit); for (i = BTN_LEFT; i <= BTN_TASK; i++) - set_bit(i, ptr->keybit); - ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL); - input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0); - input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0); + __set_bit(i, ptr->keybit); ret = input_register_device(ptr); if (ret) { @@ -271,7 +285,7 @@ static void xenkbd_backend_changed(struct xenbus_device *dev, enum xenbus_state backend_state) { struct xenkbd_info *info = dev_get_drvdata(&dev->dev); - int ret, val; + int val; switch (backend_state) { case XenbusStateInitialising: @@ -282,17 +296,6 @@ static void xenkbd_backend_changed(struct xenbus_device *dev, case XenbusStateInitWait: InitWait: - ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend, - "feature-abs-pointer", "%d", &val); - if (ret < 0) - val = 0; - if (val) { - ret = xenbus_printf(XBT_NIL, info->xbdev->nodename, - "request-abs-pointer", "1"); - if (ret) - printk(KERN_WARNING - "xenkbd: can't request abs-pointer"); - } xenbus_switch_state(dev, XenbusStateConnected); break; -- cgit v1.2.3 From 4214a0da0bdd0a7d11a7b560dfed69617d2a6dab Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 22 Mar 2011 18:40:10 -0400 Subject: SUNRPC: Never reuse the socket port after an xs_close() commit 246408dcd5dfeef2df437ccb0ef4d6ee87805f58 upstream. If we call xs_close(), we're in one of two situations: - Autoclose, which means we don't expect to resend a request - bind+connect failed, which probably means the port is in use Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/sunrpc/xprtsock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 7ca65c7005ea..02fbb8dc288c 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -710,6 +710,8 @@ static void xs_reset_transport(struct sock_xprt *transport) if (sk == NULL) return; + transport->srcport = 0; + write_lock_bh(&sk->sk_callback_lock); transport->inet = NULL; transport->sock = NULL; -- cgit v1.2.3 From 0fce96e0a736b60c49c4a1f8a37be56fe02d02b7 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 18 Nov 2010 20:52:55 -0500 Subject: fs: call security_d_instantiate in d_obtain_alias V2 commit 24ff6663ccfdaf088dfa7acae489cb11ed4f43c4 upstream. While trying to track down some NFS problems with BTRFS, I kept noticing I was getting -EACCESS for no apparent reason. Eric Paris and printk() helped me figure out that it was SELinux that was giving me grief, with the following denial type=AVC msg=audit(1290013638.413:95): avc: denied { 0x800000 } for pid=1772 comm="nfsd" name="" dev=sda1 ino=256 scontext=system_u:system_r:kernel_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=file Turns out this is because in d_obtain_alias if we can't find an alias we create one and do all the normal instantiation stuff, but we don't do the security_d_instantiate. Usually we are protected from getting a hashed dentry that hasn't yet run security_d_instantiate() by the parent's i_mutex, but obviously this isn't an option there, so in order to deal with the case that a second thread comes in and finds our new dentry before we get to run security_d_instantiate(), we go ahead and call it if we find a dentry already. Eric assures me that this is ok as the code checks to see if the dentry has been initialized already so calling security_d_instantiate() against the same dentry multiple times is ok. With this patch I'm no longer getting errant -EACCESS values. Signed-off-by: Josef Bacik Signed-off-by: Al Viro Signed-off-by: Andi Kleen Cc: Chuck Ebbert Signed-off-by: Greg Kroah-Hartman --- fs/dcache.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/dcache.c b/fs/dcache.c index 86d4db15473e..c1f86c734540 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1186,9 +1186,12 @@ struct dentry *d_obtain_alias(struct inode *inode) spin_unlock(&tmp->d_lock); spin_unlock(&dcache_lock); + security_d_instantiate(tmp, inode); return tmp; out_iput: + if (res && !IS_ERR(res)) + security_d_instantiate(res, inode); iput(inode); return res; } -- cgit v1.2.3 From cef20fc68de94ffc279b8f56205d47cd591dd42b Mon Sep 17 00:00:00 2001 From: Stuart Hayes Date: Wed, 2 Mar 2011 13:42:05 +0100 Subject: dcdbas: force SMI to happen when expected commit dd65c736d1b5312c80c88a64bf521db4959eded5 upstream. The dcdbas driver can do an I/O write to cause a SMI to occur. The SMI handler looks at certain registers and memory locations, so the SMI needs to happen immediately. On some systems I/O writes are posted, though, causing the SMI to happen well after the "outb" occurred, which causes random failures. Following the "outb" with an "inb" forces the write to go through even if it is posted. Signed-off-by: Stuart Hayes Acked-by: Doug Warzecha Signed-off-by: Andi Kleen Cc: Chuck Ebbert Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/dcdbas.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index aa9bc9e980e1..dad21fddf558 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c @@ -268,8 +268,10 @@ int dcdbas_smi_request(struct smi_cmd *smi_cmd) } /* generate SMI */ + /* inb to force posted write through and make SMI happen now */ asm volatile ( - "outb %b0,%w1" + "outb %b0,%w1\n" + "inb %w1" : /* no output args */ : "a" (smi_cmd->command_code), "d" (smi_cmd->command_address), -- cgit v1.2.3 From 083dda3eb79e0ec653ed81ffe9cc2c29cc8ab1b8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 23 Mar 2011 22:54:32 +0100 Subject: ALSA: hda - Fix SPDIF out regression on ALC889 commit 20b67dddcc5f29d3d0c900225d85e0ac655bc69d upstream. The commit 5a8cfb4e8ae317d283f84122ed20faa069c5e0c4 ALSA: hda - Use ALC_INIT_DEFAULT for really default initialization changed to use the default initialization method for ALC889, but this caused a regression on SPDIF output on some machines. This seems due to the COEF setup included in the default init procedure. For making SPDIF working again, the COEF-setup has to be avoided for the id 0889. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=24342 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b6b59a577f6c..2f06425a2551 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1161,7 +1161,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) case 0x10ec0883: case 0x10ec0885: case 0x10ec0887: - case 0x10ec0889: + /*case 0x10ec0889:*/ /* this causes an SPDIF problem */ alc889_coef_init(codec); break; case 0x10ec0888: -- cgit v1.2.3 From ed2debec5324a5382823bbfca2d493424f2d78f0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 24 Mar 2011 09:50:15 +0100 Subject: ALSA: Fix yet another race in disconnection commit a45e3d6b13e97506b616980c0f122c3389bcefa4 upstream. This patch fixes a race between snd_card_file_remove() and snd_card_disconnect(). When the card is added to shutdown_files list in snd_card_disconnect(), but it's freed in snd_card_file_remove() at the same time, the shutdown_files list gets corrupted. The list member must be freed in snd_card_file_remove() as well. Reported-and-tested-by: Russ Dill Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/core/init.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/core/init.c b/sound/core/init.c index ec4a50ce5656..82f350e00cbe 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -848,6 +848,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file) return -ENOMEM; mfile->file = file; mfile->disconnected_f_op = NULL; + INIT_LIST_HEAD(&mfile->shutdown_list); spin_lock(&card->files_lock); if (card->shutdown) { spin_unlock(&card->files_lock); @@ -883,6 +884,9 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) list_for_each_entry(mfile, &card->files_list, list) { if (mfile->file == file) { list_del(&mfile->list); + spin_lock(&shutdown_lock); + list_del(&mfile->shutdown_list); + spin_unlock(&shutdown_lock); if (mfile->disconnected_f_op) fops_put(mfile->disconnected_f_op); found = mfile; -- cgit v1.2.3 From f64186a734ac08b03842f785217ef5aa3ebdc559 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 23 Mar 2011 19:29:39 +0100 Subject: perf: Better fit max unprivileged mlock pages for tools needs commit 880f57318450dbead6a03f9e31a1468924d6dd88 upstream. The maximum kilobytes of locked memory that an unprivileged user can reserve is of 512 kB = 128 pages by default, scaled to the number of onlined CPUs, which fits well with the tools that use 128 data pages by default. However tools actually use 129 pages, because they need one more for the user control page. Thus the default mlock threshold is not sufficient for the default tools needs and we always end up to evaluate the constant mlock rlimit policy, which doesn't have this scaling with the number of online CPUs. Hence, on systems that have more than 16 CPUs, we overlap the rlimit threshold and fail to mmap: $ perf record ls Error: failed to mmap with 1 (Operation not permitted) Just increase the max unprivileged mlock threshold by one page so that it supports well perf tools even after 16 CPUs. Reported-by: Han Pingtian Reported-by: Peter Zijlstra Reported-by: Arnaldo Carvalho de Melo Signed-off-by: Frederic Weisbecker Acked-by: Arnaldo Carvalho de Melo Signed-off-by: Andi Kleen Cc: Stephane Eranian LKML-Reference: <1300904979-5508-1-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/perf_event.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/perf_event.c b/kernel/perf_event.c index d1a6c04d8399..5f559b19c26a 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -58,7 +58,8 @@ static atomic_t nr_task_events __read_mostly; */ int sysctl_perf_event_paranoid __read_mostly = 1; -int sysctl_perf_event_mlock __read_mostly = 512; /* 'free' kb per user */ +/* Minimum for 128 pages + 1 for the user control page */ +int sysctl_perf_event_mlock __read_mostly = 516; /* 'free' kb per user */ /* * max perf event sample rate -- cgit v1.2.3 From 7d90e50de05ac6589b9109039fa15b778522c62a Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 23 Mar 2011 02:44:30 +0000 Subject: myri10ge: fix rmmod crash commit cda6587c21a887254c8ed4b58da8fcc4040ab557 upstream. Rmmod myri10ge crash at free_netdev() -> netif_napi_del(), because napi structures are already deallocated. To fix call netif_napi_del() before kfree() at myri10ge_free_slices(). Signed-off-by: Stanislaw Gruszka Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/myri10ge/myri10ge.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index e0b47cc8a86e..2437c7e1e560 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -3600,6 +3600,7 @@ static void myri10ge_free_slices(struct myri10ge_priv *mgp) dma_free_coherent(&pdev->dev, bytes, ss->fw_stats, ss->fw_stats_bus); ss->fw_stats = NULL; + netif_napi_del(&ss->napi); } } kfree(mgp->ss); -- cgit v1.2.3 From d6b391f4879ddcc92f3f46dca793aaaa2cb1a84e Mon Sep 17 00:00:00 2001 From: Bud Brown Date: Wed, 23 Mar 2011 20:47:11 +0100 Subject: cciss: fix lost command issue commit 1ddd5049545e0aa1a0ed19bca4d9c9c3ce1ac8a2 upstream. Under certain workloads a command may seem to get lost. IOW, the Smart Array thinks all commands have been completed but we still have commands in our completion queue. This may lead to system instability, filesystems going read-only, or even panics depending on the affected filesystem. We add an extra read to force the write to complete. Testing shows this extra read avoids the problem. Signed-off-by: Mike Miller Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/block/cciss.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index c5d411174db0..37a2d4fb01d8 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h @@ -173,6 +173,7 @@ static void SA5_submit_command( ctlr_info_t *h, CommandList_struct *c) printk("Sending %x - down to controller\n", c->busaddr ); #endif /* CCISS_DEBUG */ writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET); + readl(h->vaddr + SA5_REQUEST_PORT_OFFSET); h->commands_outstanding++; if ( h->commands_outstanding > h->max_outstanding) h->max_outstanding = h->commands_outstanding; -- cgit v1.2.3 From 8c389a3b0274f3bf86724d2776973071ac86dbdb Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 23 Mar 2011 11:42:57 -0400 Subject: sound/oss/opl3: validate voice and channel indexes commit 4d00135a680727f6c3be78f8befaac009030e4df upstream. User-controllable indexes for voice and channel values may cause reading and writing beyond the bounds of their respective arrays, leading to potentially exploitable memory corruption. Validate these indexes. Signed-off-by: Dan Rosenberg Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/oss/opl3.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c index 938c48c43585..f4ffdff9b245 100644 --- a/sound/oss/opl3.c +++ b/sound/oss/opl3.c @@ -849,6 +849,10 @@ static int opl3_load_patch(int dev, int format, const char __user *addr, static void opl3_panning(int dev, int voice, int value) { + + if (voice < 0 || voice >= devc->nr_voice) + return; + devc->voc[voice].panning = value; } @@ -1066,8 +1070,15 @@ static int opl3_alloc_voice(int dev, int chn, int note, struct voice_alloc_info static void opl3_setup_voice(int dev, int voice, int chn) { - struct channel_info *info = - &synth_devs[dev]->chn_info[chn]; + struct channel_info *info; + + if (voice < 0 || voice >= devc->nr_voice) + return; + + if (chn < 0 || chn > 15) + return; + + info = &synth_devs[dev]->chn_info[chn]; opl3_set_instr(dev, voice, info->pgm_num); -- cgit v1.2.3 From 6e59c823bf33fbbf211fa55198aafaf125fab95f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 21 Mar 2011 20:01:00 +0100 Subject: mac80211: initialize sta->last_rx in sta_info_alloc commit 8bc8aecdc5e26cfda12dbd6867af4aa67836da6a upstream. This field is used to determine the inactivity time. When in AP mode, hostapd uses it for kicking out inactive clients after a while. Without this patch, hostapd immediately deauthenticates a new client if it checks the inactivity time before the client sends its first data frame. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/mac80211/sta_info.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index ba9360a475b0..cd6999e422f8 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -239,6 +239,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, memcpy(sta->sta.addr, addr, ETH_ALEN); sta->local = local; sta->sdata = sdata; + sta->last_rx = jiffies; if (sta_prepare_rate_control(local, sta, gfp)) { kfree(sta); -- cgit v1.2.3 From 4fec50c333c8b4ed55ba05320b781e63ed829e8d Mon Sep 17 00:00:00 2001 From: John Hughes Date: Wed, 4 Nov 2009 19:01:22 +0100 Subject: ses: show devices for enclosures with no page 7 commit 877a55979c189c590e819a61cbbe2b7947875f17 upstream. enclosure page 7 gives us the "pretty" names of the enclosure slots. Without a page 7, we can still use the enclosure code as long as we make up numeric names for the slots. Unfortunately, the current code fails to add any devices because the check for page 10 is in the wrong place if we have no page 7. Fix it so that devices show up even if the enclosure has no page 7. Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/scsi/ses.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index 7f5a6a86f820..3b00e907b917 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c @@ -390,9 +390,9 @@ static void ses_enclosure_data_process(struct enclosure_device *edev, len = (desc_ptr[2] << 8) + desc_ptr[3]; /* skip past overall descriptor */ desc_ptr += len + 4; - if (ses_dev->page10) - addl_desc_ptr = ses_dev->page10 + 8; } + if (ses_dev->page10) + addl_desc_ptr = ses_dev->page10 + 8; type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11]; components = 0; for (i = 0; i < types; i++, type_ptr += 4) { -- cgit v1.2.3 From 5d61725bfd063c59dca2d72edacfe1e217efc457 Mon Sep 17 00:00:00 2001 From: "Krishnasamy, Somasundaram" Date: Mon, 28 Feb 2011 18:13:22 -0500 Subject: ses: Avoid kernel panic when lun 0 is not mapped commit d1e12de804f9d8ad114786ca7c2ce593cba79891 upstream. During device discovery, scsi mid layer sends INQUIRY command to LUN 0. If the LUN 0 is not mapped to host, it creates a temporary scsi_device with LUN id 0 and sends REPORT_LUNS command to it. After the REPORT_LUNS succeeds, it walks through the LUN table and adds each LUN found to sysfs. At the end of REPORT_LUNS lun table scan, it will delete the temporary scsi_device of LUN 0. When scsi devices are added to sysfs, it calls add_dev function of all the registered class interfaces. If ses driver has been registered, ses_intf_add() of ses module will be called. This function calls scsi_device_enclosure() to check the inquiry data for EncServ bit. Since inquiry was not allocated for temporary LUN 0 scsi_device, it will cause NULL pointer exception. To fix the problem, sdev->inquiry is checked for NULL before reading it. Signed-off-by: Somasundaram Krishnasamy Signed-off-by: Babu Moger Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/scsi/scsi_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index d80b6dbed1ca..558fa2f13087 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -451,7 +451,7 @@ static inline int scsi_device_qas(struct scsi_device *sdev) } static inline int scsi_device_enclosure(struct scsi_device *sdev) { - return sdev->inquiry[6] & (1<<6); + return sdev->inquiry ? (sdev->inquiry[6] & (1<<6)) : 1; } static inline int scsi_device_protection(struct scsi_device *sdev) -- cgit v1.2.3 From d28a97ca224292508122da0cb92a321cc8b5bb4f Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Wed, 9 Mar 2011 11:49:13 -0600 Subject: eCryptfs: Unlock page in write_begin error path commit 50f198ae16ac66508d4b8d5a40967a8507ad19ee upstream. Unlock the page in error path of ecryptfs_write_begin(). This may happen, for example, if decryption fails while bring the page up-to-date. Signed-off-by: Tyler Hicks Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ecryptfs/mmap.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index b1d82756544b..b530d9cd5bf0 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -368,6 +368,11 @@ static int ecryptfs_write_begin(struct file *file, && (pos != 0)) zero_user(page, 0, PAGE_CACHE_SIZE); out: + if (unlikely(rc)) { + unlock_page(page); + page_cache_release(page); + *pagep = NULL; + } return rc; } -- cgit v1.2.3 From 82c2780e98b244e76ee4ec346f08499409c370df Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 17 Mar 2011 12:48:50 +0100 Subject: eCryptfs: ecryptfs_keyring_auth_tok_for_sig() bug fix commit 1821df040ac3cd6a57518739f345da6d50ea9d3f upstream. The pointer '(*auth_tok_key)' is set to NULL in case request_key() fails, in order to prevent its use by functions calling ecryptfs_keyring_auth_tok_for_sig(). Signed-off-by: Roberto Sassu Signed-off-by: Tyler Hicks Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ecryptfs/keystore.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 89c5476506ef..d6e935541a0b 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -1543,6 +1543,7 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key, printk(KERN_ERR "Could not find key with description: [%s]\n", sig); rc = process_request_key_err(PTR_ERR(*auth_tok_key)); + (*auth_tok_key) = NULL; goto out; } (*auth_tok) = ecryptfs_get_key_payload_data(*auth_tok_key); -- cgit v1.2.3 From 3bb2757ba74f0898c7d80d00407887e377a3f238 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 20 Sep 2010 19:44:38 +0200 Subject: PM / Hibernate: Improve comments in hibernate_preallocate_memory() [ upstream commit 266f1a25eff5ff98c498d7754a419aacfd88f71c ] One comment in hibernate_preallocate_memory() is wrong, so fix it and add one more comment to clarify the meaning of the fixed one. Signed-off-by: Rafael J. Wysocki Signed-off-by: Andi Kleen --- kernel/power/snapshot.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 1a9b32607339..f2f61fa7eb99 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -1318,12 +1318,14 @@ int hibernate_preallocate_memory(void) /* Compute the maximum number of saveable pages to leave in memory. */ max_size = (count - (size + PAGES_FOR_IO)) / 2 - 2 * SPARE_PAGES; + /* Compute the desired number of image pages specified by image_size. */ size = DIV_ROUND_UP(image_size, PAGE_SIZE); if (size > max_size) size = max_size; /* - * If the maximum is not less than the current number of saveable pages - * in memory, allocate page frames for the image and we're done. + * If the desired number of image pages is at least as large as the + * current number of saveable pages in memory, allocate page frames for + * the image and we're done. */ if (size >= saveable) { pages = preallocate_image_highmem(save_highmem); -- cgit v1.2.3 From b3b49f6609e293e8a9d17f24911a2dc771ee3679 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 20 Sep 2010 19:44:56 +0200 Subject: PM / Hibernate: Make default image size depend on total RAM size [ upstream commit ac5c24ec1e983313ef0015258fba6f630e54e7cf ] The default hibernation image size is currently hard coded and euqal to 500 MB, which is not a reasonable default on many contemporary systems. Make it equal 2/5 of the total RAM size (this is slightly below the maximum, i.e. 1/2 of the total RAM size, and seems to be generally suitable). Signed-off-by: Rafael J. Wysocki Tested-by: M. Vefa Bicakci Signed-off-by: Andi Kleen --- Documentation/power/interface.txt | 2 +- kernel/power/main.c | 1 + kernel/power/power.h | 9 ++++++++- kernel/power/snapshot.c | 7 ++++++- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Documentation/power/interface.txt b/Documentation/power/interface.txt index e67211fe0ee2..c537834af005 100644 --- a/Documentation/power/interface.txt +++ b/Documentation/power/interface.txt @@ -57,7 +57,7 @@ smallest image possible. In particular, if "0" is written to this file, the suspend image will be as small as possible. Reading from this file will display the current image size limit, which -is set to 500 MB by default. +is set to 2/5 of available RAM by default. /sys/power/pm_trace controls the code which saves the last PM event point in the RTC across reboots, so that you can debug a machine that just hangs diff --git a/kernel/power/main.c b/kernel/power/main.c index b58800b21fc0..51e2643e2d9d 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -266,6 +266,7 @@ static int __init pm_init(void) int error = pm_start_workqueue(); if (error) return error; + hibernate_image_size_init(); power_kobj = kobject_create_and_add("power", NULL); if (!power_kobj) return -ENOMEM; diff --git a/kernel/power/power.h b/kernel/power/power.h index 006270fe382d..54580cb4eaa7 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -14,6 +14,9 @@ struct swsusp_info { } __attribute__((aligned(PAGE_SIZE))); #ifdef CONFIG_HIBERNATION +/* kernel/power/snapshot.c */ +extern void __init hibernate_image_size_init(void); + #ifdef CONFIG_ARCH_HIBERNATION_HEADER /* Maximum size of architecture specific data in a hibernation header */ #define MAX_ARCH_HEADER_SIZE (sizeof(struct new_utsname) + 4) @@ -49,7 +52,11 @@ static inline char *check_image_kernel(struct swsusp_info *info) extern int hibernation_snapshot(int platform_mode); extern int hibernation_restore(int platform_mode); extern int hibernation_platform_enter(void); -#endif + +#else /* !CONFIG_HIBERNATION */ + +static inline void hibernate_image_size_init(void) {} +#endif /* !CONFIG_HIBERNATION */ extern int pfn_is_nosave(unsigned long); diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index f2f61fa7eb99..4d8548da48c5 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -46,7 +46,12 @@ static void swsusp_unset_page_forbidden(struct page *); * size will not exceed N bytes, but if that is impossible, it will * try to create the smallest image possible. */ -unsigned long image_size = 500 * 1024 * 1024; +unsigned long image_size; + +void __init hibernate_image_size_init(void) +{ + image_size = ((totalram_pages * 2) / 5) * PAGE_SIZE; +} /* List of PBEs needed for restoring the pages that were allocated before * the suspend and included in the suspend image, but have also been -- cgit v1.2.3 From 79a03efd3311c204f22e92cdf1a4c0d63e1c759c Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Wed, 26 May 2010 12:00:10 -0300 Subject: classmate-laptop: depends on RFKILL or RFKILL=n [ upstream commit f35843ed8d17562f7c5da4b34a4a81b0cc450e9e ] Randy Dunlap has reported that building classmate-laptop fails when CONFIG_RFKILL=m and CONFIG_ACPI_CMPC=y. He suggested depending on RFKILL, but, then, it will not be possible to select classmate-laptop when RFKILL is off. There's no known problem with building and using classmate-laptop with RFKILL off. So depend on RFKILL or RFKILL=n. Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: Matthew Garrett Signed-off-by: Andi Kleen Reported-by: Randy Dunlap Cc: Randy Dunlap Cc: platform-driver-x86@vger.kernel.org Cc: Daniel Oliveira Nascimento --- drivers/platform/x86/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 3e1b8a288719..fe7d67058eb8 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -520,6 +520,7 @@ config TOSHIBA_BT_RFKILL config ACPI_CMPC tristate "CMPC Laptop Extras" depends on X86 && ACPI + depends on RFKILL || RFKILL=n select INPUT select BACKLIGHT_CLASS_DEVICE default n -- cgit v1.2.3 From 7c8864bea48017a5166baa01f3bd81bf7ad623d7 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 1 Feb 2011 16:03:46 +0100 Subject: netfilter: arpt_mangle: fix return values of checkentry In 135367b "netfilter: xtables: change xt_target.checkentry return type", the type returned by checkentry was changed from boolean to int, but the return values where not adjusted. arptables: Input/output error This broke arptables with the mangle target since it returns true under success, which is interpreted by xtables as >0, thus returning EIO. The following Linux kernels are affected: * 2.6.35.9 * 2.6.36.4 * 2.6.37.3 Cc: stable@kernel.org Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy Signed-off-by: Andi Kleen (cherry picked from commit 9d0db8b6b1da9e3d4c696ef29449700c58d589db) --- net/ipv4/netfilter/arpt_mangle.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c index e1be7dd1171b..1dcf5d247bd7 100644 --- a/net/ipv4/netfilter/arpt_mangle.c +++ b/net/ipv4/netfilter/arpt_mangle.c @@ -60,12 +60,12 @@ static int checkentry(const struct xt_tgchk_param *par) if (mangle->flags & ~ARPT_MANGLE_MASK || !(mangle->flags & ARPT_MANGLE_MASK)) - return false; + return -EINVAL; if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT && mangle->target != ARPT_CONTINUE) - return false; - return true; + return -EINVAL; + return 0; } static struct xt_target arpt_mangle_reg __read_mostly = { -- cgit v1.2.3 From 04d450668aa58e6202916ad870cdfc73621dee26 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 31 Mar 2011 11:58:52 -0700 Subject: Patch cab9e9848b9a8283b0504a2d7c435a9f5ba026de to the 2.6.35.y stable tree stored a ref to the current cred struct in struct scm_cookie. This was fine with AF_UNIX as that calls scm_destroy() from its packet sending functions, but AF_NETLINK, which also uses scm_send(), does not call scm_destroy() - meaning that the copied credentials leak each time SCM data is sent over a netlink socket. This can be triggered quite simply on a Fedora 13 or 14 userspace with the 2.6.35.11 kernel (or something based off of that) by calling: #!/bin/bash for ((i=0; i<100; i++)) do su - -c /bin/true cut -d: -f1 /proc/slabinfo | grep 'cred\|key\|task_struct' cat /proc/keys | wc -l done This leaks the session key that pam_keyinit creates for 'su -', which appears in /proc/keys as being revoked (has the R flag set against it) afterward su is called. Furthermore, if CONFIG_SLAB=y, then the cred and key slab object usage counts can be viewed and seen to increase. The key slab increases by one object per loop, and this can be seen after the system has had a couple of minutes to stand after the script above has been run on it. If the system is working correctly, the key and cred counts should return to roughly what they were before. This patch from upstream (b47030c71dfd6c8cd5cb6e551b6f7f7cfc96f6a6) is needed to fix the problem: =============================================================================== From: Eric W. Biederman af_netlink: Add needed scm_destroy after scm_send. scm_send occasionally allocates state in the scm_cookie, so I have modified netlink_sendmsg to guarantee that when scm_send succeeds scm_destory will be called to free that state. Signed-off-by: Eric W. Biederman Signed-off-by: Andi Kleen Reviewed-by: Daniel Lezcano Acked-by: Pavel Emelyanov Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 56ed59eea69c..eb1647873261 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1323,8 +1323,11 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, if (msg->msg_flags&MSG_OOB) return -EOPNOTSUPP; - if (NULL == siocb->scm) + if (NULL == siocb->scm) { siocb->scm = &scm; + memset(&scm, 0, sizeof(scm)); + } + err = scm_send(sock, msg, siocb->scm); if (err < 0) return err; -- cgit v1.2.3 From 40478e1a3440c6b5e0f5fd81133494aefaf11ec2 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 31 Mar 2011 11:58:52 -0700 Subject: revert misc: uss720.c: add another vendor/product ID In 2.6.35.10: [ 122.146074] usb 2-1: new full speed USB device using uhci_hcd and address 2 [ 122.325102] usb 2-1: New USB device found, idVendor=050d, idProduct=0002 [ 122.325110] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 [ 122.325117] usb 2-1: Product: IEEE-1284 Controller [ 122.325121] usb 2-1: Manufacturer: Belk USB Printing Support [ 123.531167] usblp0: USB Bidirectional printer dev 2 if 0 alt 1 proto 2 vid 0x050D pid 0x0002 [ 123.531208] usbcore: registered new interface driver usblp In 2.6.35.11: [ 8046.227051] usb 2-1: new full speed USB device using uhci_hcd and address 6 [ 8046.408083] usb 2-1: New USB device found, idVendor=050d, idProduct=0002 [ 8046.408088] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 [ 8046.408092] usb 2-1: Product: IEEE-1284 Controller [ 8046.408094] usb 2-1: Manufacturer: Belk USB Printing Support [ 8047.552140] get_1284_register timeout [ 8047.554102] uss720: async_complete: urb error -104 [repeats] [ 8047.556111] uss720: async_complete: urb error -32 [sequence repeats] [unplug connector] [ 8485.688067] parport0: fix this legacy no-device port driver! [ 8485.688427] uss720: async_complete: urb error -32 Blacklisting the uss720 driver fixes the problem. From 0a67b7cf26d73ed1dbea7e99d63673b5c4aa479e Mon Sep 17 00:00:00 2001 From: Thomas Sailer Date: Tue, 14 Dec 2010 16:04:05 +0100 Subject: [PATCH] USB: misc: uss720.c: add another vendor/product ID commit ecc1624a2fff45780959efbcb73ace18fdb3c58d upstream. Fabio Battaglia report that he has another cable that works with this driver, so this patch adds its vendor/product ID. Signed-off-by: Thomas Sailer Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/misc/uss720.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 9727daa1cc72..238033800c8e 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -3,7 +3,7 @@ /* * uss720.c -- USS720 USB Parport Cable. * - * Copyright (C) 1999, 2005, 2010 + * Copyright (C) 1999, 2005 * Thomas Sailer (t.sailer@alumni.ethz.ch) * * This program is free software; you can redistribute it and/or modify @@ -775,8 +775,6 @@ static const struct usb_device_id uss720_table[] = { { USB_DEVICE(0x0557, 0x2001) }, { USB_DEVICE(0x0729, 0x1284) }, { USB_DEVICE(0x1293, 0x0002) }, - { USB_DEVICE(0x1293, 0x0002) }, - { USB_DEVICE(0x050d, 0x0002) }, { } /* Terminating entry */ }; -- cgit v1.2.3 From e3f1f25fa0344e4a981e8f5e5d5c3457ed420d35 Mon Sep 17 00:00:00 2001 From: Mark Mentovai Date: Wed, 17 Nov 2010 16:34:37 -0500 Subject: cfg80211: fix can_beacon_sec_chan, reenable HT40 [ upstream commit 09a02fdb919876c01e8f05960750a418b3f7fa48 ] This follows wireless-testing 9236d838c920e90708570d9bbd7bb82d30a38130 ("cfg80211: fix extension channel checks to initiate communication") and fixes accidental case fall-through. Without this fix, HT40 is entirely blocked. Signed-off-by: Mark Mentovai Signed-off-by: Andi Kleen Cc: stable@kernel.org Acked-by: Luis R. Rodriguez --- net/wireless/chan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 93d89d607d5a..bbaab4b0a4b6 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -53,8 +53,10 @@ static bool can_beacon_sec_chan(struct wiphy *wiphy, switch (channel_type) { case NL80211_CHAN_HT40PLUS: diff = 20; + break; case NL80211_CHAN_HT40MINUS: diff = -20; + break; default: return false; } -- cgit v1.2.3 From cce6b81802386a32a6f13ff65974431a97070dc9 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 31 Mar 2011 11:58:53 -0700 Subject: USB: isp1760: Implement solution for erratum 2 The document says: |2.1 Problem description | When at least two USB devices are simultaneously running, it is observed that | sometimes the INT corresponding to one of the USB devices stops occurring. This may | be observed sometimes with USB-to-serial or USB-to-network devices. | The problem is not noticed when only USB mass storage devices are running. |2.2 Implication | This issue is because of the clearing of the respective Done Map bit on reading the ATL | PTD Done Map register when an INT is generated by another PTD completion, but is not | found set on that read access. In this situation, the respective Done Map bit will remain | reset and no further INT will be asserted so the data transfer corresponding to that USB | device will stop. |2.3 Workaround | An SOF INT can be used instead of an ATL INT with polling on Done bits. A time-out can | be implemented and if a certain Done bit is never set, verification of the PTD completion | can be done by reading PTD contents (valid bit). | This is a proven workaround implemented in software. Russell King run into this with an USB-to-serial converter. This patch implements his suggestion to enable the high frequent SOF interrupt only at the time we have ATL packages queued. It goes even one step further and enables the SOF interrupt only if we have more than one ATL packet queued at the same time. Cc: # [2.6.35.x, 2.6.36.x, 2.6.37.x] Tested-by: Russell King Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/isp1760-hcd.c | 22 ++++++++++++++++------ drivers/usb/host/isp1760-hcd.h | 1 + 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index dbcafa29c775..e0eed11b3189 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -33,6 +33,7 @@ struct isp1760_hcd { struct inter_packet_info atl_ints[32]; struct inter_packet_info int_ints[32]; struct memory_chunk memory_pool[BLOCKS]; + u32 atl_queued; /* periodic schedule support */ #define DEFAULT_I_TDPS 1024 @@ -850,6 +851,11 @@ static void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, skip_map &= ~queue_entry; isp1760_writel(skip_map, hcd->regs + HC_ATL_PTD_SKIPMAP_REG); + priv->atl_queued++; + if (priv->atl_queued == 2) + isp1760_writel(INTERRUPT_ENABLE_SOT_MASK, + hcd->regs + HC_INTERRUPT_ENABLE); + buffstatus = isp1760_readl(hcd->regs + HC_BUFFER_STATUS_REG); buffstatus |= ATL_BUFFER; isp1760_writel(buffstatus, hcd->regs + HC_BUFFER_STATUS_REG); @@ -991,6 +997,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd) u32 dw3; status = 0; + priv->atl_queued--; queue_entry = __ffs(done_map); done_map &= ~(1 << queue_entry); @@ -1053,11 +1060,6 @@ static void do_atl_int(struct usb_hcd *usb_hcd) * device is not able to send data fast enough. * This happens mostly on slower hardware. */ - printk(KERN_NOTICE "Reloading ptd %p/%p... qh %p read: " - "%d of %zu done: %08x cur: %08x\n", qtd, - urb, qh, PTD_XFERRED_LENGTH(dw3), - qtd->length, done_map, - (1 << queue_entry)); /* RL counter = ERR counter */ dw3 &= ~(0xf << 19); @@ -1085,6 +1087,11 @@ static void do_atl_int(struct usb_hcd *usb_hcd) priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs + atl_regs, sizeof(ptd)); + priv->atl_queued++; + if (priv->atl_queued == 2) + isp1760_writel(INTERRUPT_ENABLE_SOT_MASK, + usb_hcd->regs + HC_INTERRUPT_ENABLE); + buffstatus = isp1760_readl(usb_hcd->regs + HC_BUFFER_STATUS_REG); buffstatus |= ATL_BUFFER; @@ -1190,6 +1197,9 @@ static void do_atl_int(struct usb_hcd *usb_hcd) skip_map = isp1760_readl(usb_hcd->regs + HC_ATL_PTD_SKIPMAP_REG); } + if (priv->atl_queued <= 1) + isp1760_writel(INTERRUPT_ENABLE_MASK, + usb_hcd->regs + HC_INTERRUPT_ENABLE); } static void do_intl_int(struct usb_hcd *usb_hcd) @@ -1769,7 +1779,7 @@ static irqreturn_t isp1760_irq(struct usb_hcd *usb_hcd) goto leave; isp1760_writel(imask, usb_hcd->regs + HC_INTERRUPT_REG); - if (imask & HC_ATL_INT) + if (imask & (HC_ATL_INT | HC_SOT_INT)) do_atl_int(usb_hcd); if (imask & HC_INTL_INT) diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index 6931ef5c9650..612bce5dce03 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h @@ -69,6 +69,7 @@ void deinit_kmem_cache(void); #define HC_INTERRUPT_ENABLE 0x314 #define INTERRUPT_ENABLE_MASK (HC_INTL_INT | HC_ATL_INT | HC_EOT_INT) +#define INTERRUPT_ENABLE_SOT_MASK (HC_INTL_INT | HC_SOT_INT | HC_EOT_INT) #define HC_ISO_INT (1 << 9) #define HC_ATL_INT (1 << 8) -- cgit v1.2.3 From 94f8413636c7c43eeebee440510adc4faa19a398 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 23 Feb 2011 15:46:42 -0800 Subject: xhci: Update internal dequeue pointers after stalls. [ upstream commit bf161e85fb153c0dd5a95faca73fd6a9d237c389 ] When an endpoint stalls, the xHCI driver must move the endpoint ring's dequeue pointer past the stalled transfer. To do that, the driver issues a Set TR Dequeue Pointer command, which will complete some time later. Takashi was having issues with USB 1.1 audio devices that stalled, and his analysis of the code was that the old code would not update the xHCI driver's ring dequeue pointer after the command completes. However, the dequeue pointer is set in xhci_find_new_dequeue_state(), just before the set command is issued to the hardware. Setting the dequeue pointer before the Set TR Dequeue Pointer command completes is a dangerous thing to do, since the xHCI hardware can fail the command. Instead, store the new dequeue pointer in the xhci_virt_ep structure, and update the ring's dequeue pointer when the Set TR dequeue pointer command completes. While we're at it, make sure we can't queue another Set TR Dequeue Command while the first one is still being processed. This just won't work with the internal xHCI state code. I'm still not sure if this is the right thing to do, since we might have a case where a driver queues multiple URBs to a control ring, one of the URBs Stalls, and then the driver tries to cancel the second URB. There may be a race condition there where the xHCI driver might try to issue multiple Set TR Dequeue Pointer commands, but I would have to think very hard about how the Stop Endpoint and cancellation code works. Keep the fix simple until when/if we run into that case. This patch should be queued to kernels all the way back to 2.6.31. Signed-off-by: Sarah Sharp Tested-by: Takashi Iwai Signed-off-by: Andi Kleen Cc: stable@kernel.org --- drivers/usb/host/xhci-ring.c | 29 ++++++++++++++++++++++++++--- drivers/usb/host/xhci.h | 9 +++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 3562ba23e39b..b262e915bb4e 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -503,9 +503,6 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, addr = xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr); xhci_dbg(xhci, "New dequeue pointer = 0x%llx (DMA)\n", (unsigned long long) addr); - xhci_dbg(xhci, "Setting dequeue pointer in internal ring state.\n"); - ep_ring->dequeue = state->new_deq_ptr; - ep_ring->deq_seg = state->new_deq_seg; } static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, @@ -924,9 +921,26 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, } else { xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n", ep_ctx->deq); + if (xhci_trb_virt_to_dma(dev->eps[ep_index].queued_deq_seg, + dev->eps[ep_index].queued_deq_ptr) == + (ep_ctx->deq & ~(EP_CTX_CYCLE_MASK))) { + /* Update the ring's dequeue segment and dequeue pointer + * to reflect the new position. + */ + ep_ring->deq_seg = dev->eps[ep_index].queued_deq_seg; + ep_ring->dequeue = dev->eps[ep_index].queued_deq_ptr; + } else { + xhci_warn(xhci, "Mismatch between completed Set TR Deq " + "Ptr command & xHCI internal state.\n"); + xhci_warn(xhci, "ep deq seg = %p, deq ptr = %p\n", + dev->eps[ep_index].queued_deq_seg, + dev->eps[ep_index].queued_deq_ptr); + } } dev->eps[ep_index].ep_state &= ~SET_DEQ_PENDING; + dev->eps[ep_index].queued_deq_seg = NULL; + dev->eps[ep_index].queued_deq_ptr = NULL; /* Restart any rings with pending URBs */ ring_doorbell_for_active_rings(xhci, slot_id, ep_index); } @@ -2512,6 +2526,7 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id, u32 trb_ep_index = EP_ID_FOR_TRB(ep_index); u32 trb_stream_id = STREAM_ID_FOR_TRB(stream_id); u32 type = TRB_TYPE(TRB_SET_DEQ); + struct xhci_virt_ep *ep; addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr); if (addr == 0) { @@ -2520,6 +2535,14 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id, deq_seg, deq_ptr); return 0; } + ep = &xhci->devs[slot_id]->eps[ep_index]; + if ((ep->ep_state & SET_DEQ_PENDING)) { + xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n"); + xhci_warn(xhci, "A Set TR Deq Ptr command is pending.\n"); + return 0; + } + ep->queued_deq_seg = deq_seg; + ep->queued_deq_ptr = deq_ptr; return queue_command(xhci, lower_32_bits(addr) | cycle_state, upper_32_bits(addr), trb_stream_id, trb_slot_id | trb_ep_index | type, false); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 4a445bded9a6..5edb706f6f17 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -641,6 +641,9 @@ struct xhci_ep_ctx { #define AVG_TRB_LENGTH_FOR_EP(p) ((p) & 0xffff) #define MAX_ESIT_PAYLOAD_FOR_EP(p) (((p) & 0xffff) << 16) +/* deq bitmasks */ +#define EP_CTX_CYCLE_MASK (1 << 0) + /** * struct xhci_input_control_context @@ -743,6 +746,12 @@ struct xhci_virt_ep { struct timer_list stop_cmd_timer; int stop_cmds_pending; struct xhci_hcd *xhci; + /* Dequeue pointer and dequeue segment for a submitted Set TR Dequeue + * command. We'll need to update the ring's dequeue segment and dequeue + * pointer after the command completes. + */ + struct xhci_segment *queued_deq_seg; + union xhci_trb *queued_deq_ptr; }; struct xhci_virt_device { -- cgit v1.2.3 From 552dca81137cfd49b2b4eebffc6a3621da31e83f Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 15 Mar 2011 14:37:10 +0100 Subject: perf: Fix tear-down of inherited group events [ upstream commit 38b435b16c36b0d863efcf3f07b34a6fac9873fd ] When destroying inherited events, we need to destroy groups too, otherwise the event iteration in perf_event_exit_task_context() will miss group siblings and we leak events with all the consequences. Reported-and-tested-by: Vince Weaver Signed-off-by: Peter Zijlstra Signed-off-by: Andi Kleen Cc: # .35+ LKML-Reference: <1300196470.2203.61.camel@twins> Signed-off-by: Ingo Molnar --- kernel/perf_event.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 5f559b19c26a..fa8123e48353 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -5401,17 +5401,20 @@ __perf_event_exit_task(struct perf_event *child_event, struct perf_event_context *child_ctx, struct task_struct *child) { - struct perf_event *parent_event; + if (child_event->parent) { + raw_spin_lock_irq(&child_ctx->lock); + perf_group_detach(child_event); + raw_spin_unlock_irq(&child_ctx->lock); + } perf_event_remove_from_context(child_event); - parent_event = child_event->parent; /* - * It can happen that parent exits first, and has events + * It can happen that the parent exits first, and has events * that are still around due to the child reference. These - * events need to be zapped - but otherwise linger. + * events need to be zapped. */ - if (parent_event) { + if (child_event->parent) { sync_child_event(child_event, child); free_event(child_event); } -- cgit v1.2.3 From 15361175578d65b4be8519399d03fe1c9b6ca425 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Mon, 14 Feb 2011 17:46:21 +0200 Subject: Revert "slab: Fix missing DEBUG_SLAB last user" [ upstream commit 3ff84a7f36554b257cd57325b1a7c1fa4b49fbe3 ] This reverts commit 5c5e3b33b7cb959a401f823707bee006caadd76e. The commit breaks ARM thusly: | Mount-cache hash table entries: 512 | slab error in verify_redzone_free(): cache `idr_layer_cache': memory outside object was overwritten | Backtrace: | [] (dump_backtrace+0x0/0x110) from [] (dump_stack+0x18/0x1c) | [] (dump_stack+0x0/0x1c) from [] (__slab_error+0x28/0x30) | [] (__slab_error+0x0/0x30) from [] (cache_free_debugcheck+0x1c0/0x2b8) | [] (cache_free_debugcheck+0x0/0x2b8) from [] (kmem_cache_free+0x3c/0xc0) | [] (kmem_cache_free+0x0/0xc0) from [] (ida_get_new_above+0x19c/0x1c0) | [] (ida_get_new_above+0x0/0x1c0) from [] (alloc_vfsmnt+0x54/0x144) | [] (alloc_vfsmnt+0x0/0x144) from [] (vfs_kern_mount+0x30/0xec) | [] (vfs_kern_mount+0x0/0xec) from [] (kern_mount_data+0x1c/0x20) | [] (kern_mount_data+0x0/0x20) from [] (sysfs_init+0x68/0xc8) | [] (sysfs_init+0x0/0xc8) from [] (mnt_init+0x90/0x1b0) | [] (mnt_init+0x0/0x1b0) from [] (vfs_caches_init+0x100/0x140) | [] (vfs_caches_init+0x0/0x140) from [] (start_kernel+0x2e8/0x368) | [] (start_kernel+0x0/0x368) from [] (__enable_mmu+0x0/0x2c) | c0113268: redzone 1:0xd84156c5c032b3ac, redzone 2:0xd84156c5635688c0. | slab error in cache_alloc_debugcheck_after(): cache `idr_layer_cache': double free, or memory outside object was overwritten | ... | c011307c: redzone 1:0x9f91102ffffffff, redzone 2:0x9f911029d74e35b | slab: Internal list corruption detected in cache 'idr_layer_cache'(24), slabp c0113000(16). Hexdump: | | 000: 20 4f 10 c0 20 4f 10 c0 7c 00 00 00 7c 30 11 c0 | 010: 10 00 00 00 10 00 00 00 00 00 c9 17 fe ff ff ff | 020: fe ff ff ff fe ff ff ff fe ff ff ff fe ff ff ff | 030: fe ff ff ff fe ff ff ff fe ff ff ff fe ff ff ff | 040: fe ff ff ff fe ff ff ff fe ff ff ff fe ff ff ff | 050: fe ff ff ff fe ff ff ff fe ff ff ff 11 00 00 00 | 060: 12 00 00 00 13 00 00 00 14 00 00 00 15 00 00 00 | 070: 16 00 00 00 17 00 00 00 c0 88 56 63 | kernel BUG at /home/rmk/git/linux-2.6-rmk/mm/slab.c:2928! Reference: https://lkml.org/lkml/2011/2/7/238 Cc: # 2.6.35.y and later Reported-and-analyzed-by: Russell King Signed-off-by: Pekka Enberg Signed-off-by: Andi Kleen --- mm/slab.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index e4f747fcbdf4..91e691bf9a0e 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2289,8 +2289,8 @@ kmem_cache_create (const char *name, size_t size, size_t align, if (ralign < align) { ralign = align; } - /* disable debug if not aligning with REDZONE_ALIGN */ - if (ralign & (__alignof__(unsigned long long) - 1)) + /* disable debug if necessary */ + if (ralign > __alignof__(unsigned long long)) flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER); /* * 4) Store it. @@ -2316,8 +2316,8 @@ kmem_cache_create (const char *name, size_t size, size_t align, */ if (flags & SLAB_RED_ZONE) { /* add space for red zone words */ - cachep->obj_offset += align; - size += align + sizeof(unsigned long long); + cachep->obj_offset += sizeof(unsigned long long); + size += 2 * sizeof(unsigned long long); } if (flags & SLAB_STORE_USER) { /* user store requires one word storage behind the end of -- cgit v1.2.3 From 491da76ab1094232131cd3434cde096350e1b82c Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sat, 29 Jan 2011 14:57:22 +0000 Subject: net: Fix ip link add netns oops [ upstream commit 13ad17745c2cbd437d9e24b2d97393e0be11c439 ] Ed Swierk writes: > On 2.6.35.7 > ip link add link eth0 netns 9999 type macvlan > where 9999 is a nonexistent PID triggers an oops and causes all network functions to hang: > [10663.821898] BUG: unable to handle kernel NULL pointer dereference at 000000000000006d > [10663.821917] IP: [] __dev_alloc_name+0x9a/0x170 > [10663.821933] PGD 1d3927067 PUD 22f5c5067 PMD 0 > [10663.821944] Oops: 0000 [#1] SMP > [10663.821953] last sysfs file: /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq > [10663.821959] CPU 3 > [10663.821963] Modules linked in: macvlan ip6table_filter ip6_tables rfcomm ipt_MASQUERADE binfmt_misc iptable_nat nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_state nf_conntrack sco ipt_REJECT bnep l2cap xt_tcpudp iptable_filter ip_tables x_tables bridge stp vboxnetadp vboxnetflt vboxdrv kvm_intel kvm parport_pc ppdev snd_hda_codec_intelhdmi snd_hda_codec_conexant arc4 iwlagn iwlcore mac80211 snd_hda_intel snd_hda_codec snd_hwdep snd_pcm snd_seq_midi snd_rawmidi i915 snd_seq_midi_event snd_seq thinkpad_acpi drm_kms_helper btusb tpm_tis nvram uvcvideo snd_timer snd_seq_device bluetooth videodev v4l1_compat v4l2_compat_ioctl32 tpm drm tpm_bios snd cfg80211 psmouse serio_raw intel_ips soundcore snd_page_alloc intel_agp i2c_algo_bit video output netconsole configfs lp parport usbhid hid e1000e sdhci_pci ahci libahci sdhci led_class > [10663.822155] > [10663.822161] Pid: 6000, comm: ip Not tainted 2.6.35-23-generic #41-Ubuntu 2901CTO/2901CTO > [10663.822167] RIP: 0010:[] [] __dev_alloc_name+0x9a/0x170 > [10663.822177] RSP: 0018:ffff88014aebf7b8 EFLAGS: 00010286 > [10663.822182] RAX: 00000000fffffff4 RBX: ffff8801ad900800 RCX: 0000000000000000 > [10663.822187] RDX: ffff880000000000 RSI: 0000000000000000 RDI: ffff88014ad63000 > [10663.822191] RBP: ffff88014aebf808 R08: 0000000000000041 R09: 0000000000000041 > [10663.822196] R10: 0000000000000000 R11: dead000000200200 R12: ffff88014aebf818 > [10663.822201] R13: fffffffffffffffd R14: ffff88014aebf918 R15: ffff88014ad62000 > [10663.822207] FS: 00007f00c487f700(0000) GS:ffff880001f80000(0000) knlGS:0000000000000000 > [10663.822212] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 > [10663.822216] CR2: 000000000000006d CR3: 0000000231f19000 CR4: 00000000000026e0 > [10663.822221] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 > [10663.822226] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 > [10663.822231] Process ip (pid: 6000, threadinfo ffff88014aebe000, task ffff88014afb16e0) > [10663.822236] Stack: > [10663.822240] ffff88014aebf808 ffffffff814a2bb5 ffff88014aebf7e8 00000000a00ee8d6 > [10663.822251] <0> 0000000000000000 ffffffffa00ef940 ffff8801ad900800 ffff88014aebf818 > [10663.822265] <0> ffff88014aebf918 ffff8801ad900800 ffff88014aebf858 ffffffff8149c413 > [10663.822281] Call Trace: > [10663.822290] [] ? dev_addr_init+0x75/0xb0 > [10663.822298] [] dev_alloc_name+0x43/0x90 > [10663.822307] [] rtnl_create_link+0xbe/0x1b0 > [10663.822314] [] rtnl_newlink+0x48a/0x570 > [10663.822321] [] ? rtnl_newlink+0x1ac/0x570 > [10663.822332] [] ? native_x2apic_icr_read+0x4/0x20 > [10663.822339] [] rtnetlink_rcv_msg+0x177/0x290 > [10663.822346] [] ? rtnetlink_rcv_msg+0x0/0x290 > [10663.822354] [] netlink_rcv_skb+0xa9/0xd0 > [10663.822360] [] rtnetlink_rcv+0x25/0x40 > [10663.822367] [] netlink_unicast+0x2de/0x2f0 > [10663.822374] [] netlink_sendmsg+0x1fe/0x2e0 > [10663.822383] [] sock_sendmsg+0xf3/0x120 > [10663.822391] [] ? _raw_spin_lock+0xe/0x20 > [10663.822400] [] ? __d_lookup+0x136/0x150 > [10663.822406] [] ? _raw_spin_lock+0xe/0x20 > [10663.822414] [] ? _atomic_dec_and_lock+0x4d/0x80 > [10663.822422] [] ? mntput_no_expire+0x30/0x110 > [10663.822429] [] ? move_addr_to_kernel+0x65/0x70 > [10663.822435] [] ? verify_iovec+0x88/0xe0 > [10663.822442] [] sys_sendmsg+0x240/0x3a0 > [10663.822450] [] ? __do_fault+0x479/0x560 > [10663.822457] [] ? _raw_spin_lock+0xe/0x20 > [10663.822465] [] ? alloc_fd+0x10a/0x150 > [10663.822473] [] ? do_page_fault+0x15e/0x350 > [10663.822482] [] system_call_fastpath+0x16/0x1b > [10663.822487] Code: 90 48 8d 78 02 be 25 00 00 00 e8 92 1d e2 ff 48 85 c0 75 cf bf 20 00 00 00 e8 c3 b1 c6 ff 49 89 c7 b8 f4 ff ff ff 4d 85 ff 74 bd <4d> 8b 75 70 49 8d 45 70 48 89 45 b8 49 83 ee 58 eb 28 48 8d 55 > [10663.822618] RIP [] __dev_alloc_name+0x9a/0x170 > [10663.822627] RSP > [10663.822631] CR2: 000000000000006d > [10663.822636] ---[ end trace 3dfd6c3ad5327ca7 ]--- This bug was introduced in: commit 81adee47dfb608df3ad0b91d230fb3cef75f0060 Author: Eric W. Biederman Date: Sun Nov 8 00:53:51 2009 -0800 net: Support specifying the network namespace upon device creation. There is no good reason to not support userspace specifying the network namespace during device creation, and it makes it easier to create a network device and pass it to a child network namespace with a well known name. We have to be careful to ensure that the target network namespace for the new device exists through the life of the call. To keep that logic clear I have factored out the network namespace grabbing logic into rtnl_link_get_net. In addtion we need to continue to pass the source network namespace to the rtnl_link_ops.newlink method so that we can find the base device source network namespace. Signed-off-by: Eric W. Biederman Acked-by: Eric Dumazet Where apparently I forgot to add error handling to the path where we create a new network device in a new network namespace, and pass in an invalid pid. Cc: stable@kernel.org Reported-by: Ed Swierk Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller Signed-off-by: Andi Kleen --- net/core/rtnetlink.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 1a2af24e9e3d..04b3dcf40dc5 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1545,6 +1545,9 @@ replay: snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); dest_net = rtnl_link_get_net(net, tb); + if (IS_ERR(dest_net)) + return PTR_ERR(dest_net); + dev = rtnl_create_link(net, dest_net, ifname, ops, tb); if (IS_ERR(dev)) -- cgit v1.2.3 From b6c33e339d01d1132887d822555697b0b4bbded9 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 14 Aug 2010 21:08:55 +0200 Subject: hwmon: (w83627ehf) Driver cleanup [ upstream commit da2e025590cf7038440132d4bbc967a579b11112 ] - Moved fan pwm register array pointers into per-instance data. - Only read fan pwm data for installed/supported fans. - Update fan max output and fan step output information from data in registers. - Create max_output and step_output attribute files only if respective fan pwm registers exist. Signed-off-by: Guenter Roeck Signed-off-by: Jean Delvare Signed-off-by: Andi Kleen --- drivers/hwmon/w83627ehf.c | 59 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 0dcaba9b7189..e01a3e97aa17 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -277,6 +277,11 @@ struct w83627ehf_data { struct device *hwmon_dev; struct mutex lock; + const u8 *REG_FAN_START_OUTPUT; + const u8 *REG_FAN_STOP_OUTPUT; + const u8 *REG_FAN_MAX_OUTPUT; + const u8 *REG_FAN_STEP_OUTPUT; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -524,7 +529,10 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) } } - for (i = 0; i < 4; i++) { + for (i = 0; i < data->pwm_num; i++) { + if (!(data->has_fan & (1 << i))) + continue; + /* pwmcfg, tolerance mapped for i=0, i=1 to same reg */ if (i != 1) { pwmcfg = w83627ehf_read_value(data, @@ -546,6 +554,17 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) W83627EHF_REG_FAN_STOP_OUTPUT[i]); data->fan_stop_time[i] = w83627ehf_read_value(data, W83627EHF_REG_FAN_STOP_TIME[i]); + + if (data->REG_FAN_MAX_OUTPUT[i] != 0xff) + data->fan_max_output[i] = + w83627ehf_read_value(data, + data->REG_FAN_MAX_OUTPUT[i]); + + if (data->REG_FAN_STEP_OUTPUT[i] != 0xff) + data->fan_step_output[i] = + w83627ehf_read_value(data, + data->REG_FAN_STEP_OUTPUT[i]); + data->target_temp[i] = w83627ehf_read_value(data, W83627EHF_REG_TARGET[i]) & @@ -1126,7 +1145,7 @@ store_##reg(struct device *dev, struct device_attribute *attr, \ u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 1, 255); \ mutex_lock(&data->update_lock); \ data->reg[nr] = val; \ - w83627ehf_write_value(data, W83627EHF_REG_##REG[nr], val); \ + w83627ehf_write_value(data, data->REG_##REG[nr], val); \ mutex_unlock(&data->update_lock); \ return count; \ } @@ -1206,12 +1225,26 @@ static struct sensor_device_attribute sda_sf3_arrays[] = { store_fan_stop_output, 1), SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output, store_fan_stop_output, 2), +}; - /* pwm1 and pwm3 don't support max and step settings */ + +/* + * pwm1 and pwm3 don't support max and step settings on all chips. + * Need to check support while generating/removing attribute files. + */ +static struct sensor_device_attribute sda_sf3_max_step_arrays[] = { + SENSOR_ATTR(pwm1_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, + store_fan_max_output, 0), + SENSOR_ATTR(pwm1_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, + store_fan_step_output, 0), SENSOR_ATTR(pwm2_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, store_fan_max_output, 1), SENSOR_ATTR(pwm2_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, store_fan_step_output, 1), + SENSOR_ATTR(pwm3_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, + store_fan_max_output, 2), + SENSOR_ATTR(pwm3_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, + store_fan_step_output, 2), }; static ssize_t @@ -1235,6 +1268,12 @@ static void w83627ehf_device_remove_files(struct device *dev) for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++) device_remove_file(dev, &sda_sf3_arrays[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(sda_sf3_max_step_arrays); i++) { + struct sensor_device_attribute *attr = + &sda_sf3_max_step_arrays[i]; + if (data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff) + device_remove_file(dev, &attr->dev_attr); + } for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr); for (i = 0; i < data->in_num; i++) { @@ -1352,6 +1391,11 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) data->in6_skip = !data->temp3_disable; } + data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT; + data->REG_FAN_STOP_OUTPUT = W83627EHF_REG_FAN_STOP_OUTPUT; + data->REG_FAN_MAX_OUTPUT = W83627EHF_REG_FAN_MAX_OUTPUT; + data->REG_FAN_STEP_OUTPUT = W83627EHF_REG_FAN_STEP_OUTPUT; + /* Initialize the chip */ w83627ehf_init_device(data); @@ -1440,6 +1484,15 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) &sda_sf3_arrays[i].dev_attr))) goto exit_remove; + for (i = 0; i < ARRAY_SIZE(sda_sf3_max_step_arrays); i++) { + struct sensor_device_attribute *attr = + &sda_sf3_max_step_arrays[i]; + if (data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff) { + err = device_create_file(dev, &attr->dev_attr); + if (err) + goto exit_remove; + } + } /* if fan4 is enabled create the sf3 files for it */ if ((data->has_fan & (1 << 3)) && data->pwm_num >= 4) for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) { -- cgit v1.2.3 From ecbde8e81e12c89a4d19ba4c66afa4f8784187d3 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 24 Feb 2011 17:26:41 +1100 Subject: md: Fix - again - partition detection when array becomes active [ upstream commit f0b4f7e2f29af678bd9af43422c537dcb6008603 ] Revert b821eaa572fd737faaf6928ba046e571526c36c6 and f3b99be19ded511a1bf05a148276239d9f13eefa When I wrote the first of these I had a wrong idea about the lifetime of 'struct block_device'. It can disappear at any time that the block device is not open if it falls out of the inode cache. So relying on the 'size' recorded with it to detect when the device size has changed and so we need to revalidate, is wrong. Rather, we really do need the 'changed' attribute stored directly in the mddev and set/tested as appropriate. Without this patch, a sequence of: mknod / open / close / unlink (which can cause a block_device to be created and then destroyed) will result in a rescan of the partition table and consequence removal and addition of partitions. Several of these in a row can get udev racing to create and unlink and other code can get confused. With the patch, the rescan is only performed when needed and so there are no races. This is suitable for any stable kernel from 2.6.35. Reported-by: "Wojcik, Krzysztof" Signed-off-by: NeilBrown Signed-off-by: Andi Kleen Cc: stable@kernel.org --- drivers/md/md.c | 22 +++++++++++++++++++++- drivers/md/md.h | 2 ++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index ff1b20d4cf5f..9ec74cc604f0 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4550,6 +4550,7 @@ static int do_md_run(mddev_t *mddev) set_capacity(mddev->gendisk, mddev->array_sectors); revalidate_disk(mddev->gendisk); + mddev->changed = 1; kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); out: return err; @@ -4638,6 +4639,7 @@ static void md_clean(mddev_t *mddev) mddev->sync_speed_min = mddev->sync_speed_max = 0; mddev->recovery = 0; mddev->in_sync = 0; + mddev->changed = 0; mddev->degraded = 0; mddev->barriers_work = 0; mddev->safemode = 0; @@ -4744,6 +4746,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) set_capacity(disk, 0); revalidate = 1; + mddev->changed = 1; if (mddev->ro) mddev->ro = 0; @@ -5930,7 +5933,7 @@ static int md_open(struct block_device *bdev, fmode_t mode) atomic_inc(&mddev->openers); mutex_unlock(&mddev->open_mutex); - check_disk_size_change(mddev->gendisk, bdev); + check_disk_change(bdev); out: return err; } @@ -5945,6 +5948,21 @@ static int md_release(struct gendisk *disk, fmode_t mode) return 0; } + +static int md_media_changed(struct gendisk *disk) +{ + mddev_t *mddev = disk->private_data; + + return mddev->changed; +} + +static int md_revalidate(struct gendisk *disk) +{ + mddev_t *mddev = disk->private_data; + + mddev->changed = 0; + return 0; +} static const struct block_device_operations md_fops = { .owner = THIS_MODULE, @@ -5955,6 +5973,8 @@ static const struct block_device_operations md_fops = .compat_ioctl = md_compat_ioctl, #endif .getgeo = md_getgeo, + .media_changed = md_media_changed, + .revalidate_disk= md_revalidate, }; static int md_thread(void * arg) diff --git a/drivers/md/md.h b/drivers/md/md.h index 9ec208e11fbf..2e2a3c26c8f8 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -250,6 +250,8 @@ struct mddev_s atomic_t active; /* general refcount */ atomic_t openers; /* number of active opens */ + int changed; /* True if we might need to + * reread partition info */ int degraded; /* whether md should consider * adding a spare */ -- cgit v1.2.3 From a334427ace8de88f5257cb6431f4bfc0588c7ac7 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 21 Feb 2011 09:03:36 +0100 Subject: iwl3945: remove plcp check commit c91d01556f52255a31575be0cb1981c92a2a5028 upstream. Patch fixes: https://bugzilla.redhat.com/show_bug.cgi?id=654599 Many users report very low speed problem on 3945 devices, this patch fixes problem, but only for some of them. For unknown reason, sometimes after hw scanning, device is not able to receive frames at high rate. Since plcp health check may request hw scan to "reset radio", performance problem start to be observable after update kernel to .35, where plcp check was introduced. Bug reporter confirmed that removing plcp check fixed problem for him. Reported-and-tested-by: SilvioTO Acked-by: Wey-Yi Guy Signed-off-by: Stanislaw Gruszka Signed-off-by: Andi Kleen --- drivers/net/wireless/iwlwifi/iwl-3945.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 2a9480dab2d5..7b4fc94fee0a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2837,7 +2837,6 @@ static struct iwl_lib_ops iwl3945_lib = { .config_ap = iwl3945_config_ap, .manage_ibss_station = iwl3945_manage_ibss_station, .recover_from_tx_stall = iwl_bg_monitor_recover, - .check_plcp_health = iwl3945_good_plcp_health, .debugfs_ops = { .rx_stats_read = iwl3945_ucode_rx_stats_read, -- cgit v1.2.3 From 8295c17f384a1e50b56cacbdc0d91e1c21c1b953 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 31 Mar 2011 11:58:55 -0700 Subject: KVM: enlarge number of possible CPUID leaves commit 73c1160ce377d8fc6d84cb630ebf9658808bec49 upstream. Currently the number of CPUID leaves KVM handles is limited to 40. My desktop machine (AthlonII) already has 35 and future CPUs will expand this well beyond the limit. Extend the limit to 80 to make room for future processors. KVM-Stable-Tag. Signed-off-by: Andre Przywara Signed-off-by: Avi Kivity Signed-off-by: Andi Kleen --- arch/x86/include/asm/kvm_host.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 76f5483cffec..7342a5b63ba9 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -77,7 +77,7 @@ #define KVM_NUM_MMU_PAGES (1 << KVM_MMU_HASH_SHIFT) #define KVM_MIN_FREE_MMU_PAGES 5 #define KVM_REFILL_PAGES 25 -#define KVM_MAX_CPUID_ENTRIES 40 +#define KVM_MAX_CPUID_ENTRIES 80 #define KVM_NR_FIXED_MTRR_REGION 88 #define KVM_NR_VAR_MTRR 8 -- cgit v1.2.3 From a0e696446fddddabf00c57e1db5f38b929c3e713 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 31 Mar 2011 11:58:55 -0700 Subject: KVM: i8259: initialize isr_ack commit a0272630bb594b4eac03a79e77957df7dad8eade upstream. isr_ack is never initialized. So, until the first PIC reset, interrupts may fail to be injected. This can cause Windows XP to fail to boot, as reported in the fallout from the fix to https://bugzilla.kernel.org/show_bug.cgi?id=21962. Reported-and-tested-by: Nicolas Prochazka Signed-off-by: Avi Kivity Signed-off-by: Andi Kleen --- arch/x86/kvm/i8259.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index 93825ff3338f..8a3324668cac 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c @@ -553,6 +553,8 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm) s->irq_request_opaque = kvm; s->pics[0].pics_state = s; s->pics[1].pics_state = s; + s->pics[0].isr_ack = 0xff; + s->pics[1].isr_ack = 0xff; /* * Initialize PIO device -- cgit v1.2.3 From ae364158077225260dced4bf5f39db8c8c1289db Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Thu, 31 Mar 2011 11:58:55 -0700 Subject: Revert "KVM: Correct ordering of ldt reload wrt fs/gs reload" This reverts commit d3f813da18f83a31f2678988b450e6a1c94c95ed. Signed-off-by: Andi Kleen --- arch/x86/kvm/svm.c | 2 +- arch/x86/kvm/vmx.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 9ca703219d72..02a5603695e3 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -3184,9 +3184,9 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp; vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip; - kvm_load_ldt(ldt_selector); kvm_load_fs(fs_selector); kvm_load_gs(gs_selector); + kvm_load_ldt(ldt_selector); load_host_msrs(vcpu); reload_tss(vcpu); diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 39ac45694d51..7d043883d9bc 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -791,6 +791,8 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) ++vmx->vcpu.stat.host_state_reload; vmx->host_state.loaded = 0; + if (vmx->host_state.fs_reload_needed) + kvm_load_fs(vmx->host_state.fs_sel); if (vmx->host_state.gs_ldt_reload_needed) { kvm_load_ldt(vmx->host_state.ldt_sel); /* @@ -804,8 +806,6 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) #endif local_irq_restore(flags); } - if (vmx->host_state.fs_reload_needed) - loadsegment(fs, vmx->host_state.fs_sel); reload_tss(); #ifdef CONFIG_X86_64 if (is_long_mode(&vmx->vcpu)) { -- cgit v1.2.3 From b59a19a633904c9b1bb7fbbdb33023b1eb7ce641 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 31 Mar 2011 11:58:55 -0700 Subject: KVM: Fix fs/gs reload oops with invalid ldt commit 9581d442b9058d3699b4be568b6e5eae38a41493 upstream. kvm reloads the host's fs and gs blindly, however the underlying segment descriptors may be invalid due to the user modifying the ldt after loading them. Fix by using the safe accessors (loadsegment() and load_gs_index()) instead of home grown unsafe versions. This is CVE-2010-3698. KVM-Stable-Tag. Signed-off-by: Avi Kivity Signed-off-by: Marcelo Tosatti Signed-off-by: Andi Kleen --- arch/x86/include/asm/kvm_host.h | 24 ------------------------ arch/x86/kvm/svm.c | 15 ++++++++++----- arch/x86/kvm/vmx.c | 24 +++++++++--------------- 3 files changed, 19 insertions(+), 44 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 7342a5b63ba9..535c3738ef6b 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -673,20 +673,6 @@ static inline struct kvm_mmu_page *page_header(hpa_t shadow_page) return (struct kvm_mmu_page *)page_private(page); } -static inline u16 kvm_read_fs(void) -{ - u16 seg; - asm("mov %%fs, %0" : "=g"(seg)); - return seg; -} - -static inline u16 kvm_read_gs(void) -{ - u16 seg; - asm("mov %%gs, %0" : "=g"(seg)); - return seg; -} - static inline u16 kvm_read_ldt(void) { u16 ldt; @@ -694,16 +680,6 @@ static inline u16 kvm_read_ldt(void) return ldt; } -static inline void kvm_load_fs(u16 sel) -{ - asm("mov %0, %%fs" : : "rm"(sel)); -} - -static inline void kvm_load_gs(u16 sel) -{ - asm("mov %0, %%gs" : : "rm"(sel)); -} - static inline void kvm_load_ldt(u16 sel) { asm("lldt %0" : : "rm"(sel)); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 02a5603695e3..606de8516b3c 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -3096,8 +3096,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) sync_lapic_to_cr8(vcpu); save_host_msrs(vcpu); - fs_selector = kvm_read_fs(); - gs_selector = kvm_read_gs(); + savesegment(fs, fs_selector); + savesegment(gs, gs_selector); ldt_selector = kvm_read_ldt(); svm->vmcb->save.cr2 = vcpu->arch.cr2; /* required for live migration with NPT */ @@ -3184,10 +3184,15 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp; vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip; - kvm_load_fs(fs_selector); - kvm_load_gs(gs_selector); - kvm_load_ldt(ldt_selector); load_host_msrs(vcpu); + loadsegment(fs, fs_selector); +#ifdef CONFIG_X86_64 + load_gs_index(gs_selector); + wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs); +#else + loadsegment(gs, gs_selector); +#endif + kvm_load_ldt(ldt_selector); reload_tss(vcpu); diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 7d043883d9bc..44e74f1fde3e 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -746,7 +746,7 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu) */ vmx->host_state.ldt_sel = kvm_read_ldt(); vmx->host_state.gs_ldt_reload_needed = vmx->host_state.ldt_sel; - vmx->host_state.fs_sel = kvm_read_fs(); + savesegment(fs, vmx->host_state.fs_sel); if (!(vmx->host_state.fs_sel & 7)) { vmcs_write16(HOST_FS_SELECTOR, vmx->host_state.fs_sel); vmx->host_state.fs_reload_needed = 0; @@ -754,7 +754,7 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu) vmcs_write16(HOST_FS_SELECTOR, 0); vmx->host_state.fs_reload_needed = 1; } - vmx->host_state.gs_sel = kvm_read_gs(); + savesegment(gs, vmx->host_state.gs_sel); if (!(vmx->host_state.gs_sel & 7)) vmcs_write16(HOST_GS_SELECTOR, vmx->host_state.gs_sel); else { @@ -784,27 +784,21 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu) static void __vmx_load_host_state(struct vcpu_vmx *vmx) { - unsigned long flags; - if (!vmx->host_state.loaded) return; ++vmx->vcpu.stat.host_state_reload; vmx->host_state.loaded = 0; if (vmx->host_state.fs_reload_needed) - kvm_load_fs(vmx->host_state.fs_sel); + loadsegment(fs, vmx->host_state.fs_sel); if (vmx->host_state.gs_ldt_reload_needed) { kvm_load_ldt(vmx->host_state.ldt_sel); - /* - * If we have to reload gs, we must take care to - * preserve our gs base. - */ - local_irq_save(flags); - kvm_load_gs(vmx->host_state.gs_sel); #ifdef CONFIG_X86_64 - wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE)); + load_gs_index(vmx->host_state.gs_sel); + wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs); +#else + loadsegment(gs, vmx->host_state.gs_sel); #endif - local_irq_restore(flags); } reload_tss(); #ifdef CONFIG_X86_64 @@ -2518,8 +2512,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */ vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */ vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */ - vmcs_write16(HOST_FS_SELECTOR, kvm_read_fs()); /* 22.2.4 */ - vmcs_write16(HOST_GS_SELECTOR, kvm_read_gs()); /* 22.2.4 */ + vmcs_write16(HOST_FS_SELECTOR, 0); /* 22.2.4 */ + vmcs_write16(HOST_GS_SELECTOR, 0); /* 22.2.4 */ vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */ #ifdef CONFIG_X86_64 rdmsrl(MSR_FS_BASE, a); -- cgit v1.2.3 From 8aeabadb7ba1c1310bb968950e5f3f1793a58b19 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 31 Mar 2011 11:58:56 -0700 Subject: KVM: Correct ordering of ldt reload wrt fs/gs reload commit 0a77fe4c188e25917799f2356d4aa5e6d80c39a2 upstream. If fs or gs refer to the ldt, they must be reloaded after the ldt. Reorder the code to that effect. Userspace code that uses the ldt with kvm is nonexistent, so this doesn't fix a user-visible bug. Signed-off-by: Avi Kivity Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/kvm/svm.c | 2 +- arch/x86/kvm/vmx.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 606de8516b3c..d103e15c64f3 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -3185,6 +3185,7 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip; load_host_msrs(vcpu); + kvm_load_ldt(ldt_selector); loadsegment(fs, fs_selector); #ifdef CONFIG_X86_64 load_gs_index(gs_selector); @@ -3192,7 +3193,6 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) #else loadsegment(gs, gs_selector); #endif - kvm_load_ldt(ldt_selector); reload_tss(vcpu); diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 44e74f1fde3e..449060ea1450 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -789,8 +789,6 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) ++vmx->vcpu.stat.host_state_reload; vmx->host_state.loaded = 0; - if (vmx->host_state.fs_reload_needed) - loadsegment(fs, vmx->host_state.fs_sel); if (vmx->host_state.gs_ldt_reload_needed) { kvm_load_ldt(vmx->host_state.ldt_sel); #ifdef CONFIG_X86_64 @@ -800,6 +798,8 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) loadsegment(gs, vmx->host_state.gs_sel); #endif } + if (vmx->host_state.fs_reload_needed) + loadsegment(fs, vmx->host_state.fs_sel); reload_tss(); #ifdef CONFIG_X86_64 if (is_long_mode(&vmx->vcpu)) { -- cgit v1.2.3 From c8149a61de28892d8d28fd2180d1f9bbba2c9551 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Thu, 31 Mar 2011 11:58:56 -0700 Subject: KVM: VMX: Fix host userspace gsbase corruption commit c8770e7ba63bb5dd8fe5f9d251275a8fa717fb78 upstream. We now use load_gs_index() to load gs safely; unfortunately this also changes MSR_KERNEL_GS_BASE, which we managed separately. This resulted in confusion and breakage running 32-bit host userspace on a 64-bit kernel. Fix by - saving guest MSR_KERNEL_GS_BASE before we we reload the host's gs - doing the host save/load unconditionally, instead of only when in guest long mode Things can be cleaned up further, but this is the minmal fix for now. Signed-off-by: Avi Kivity Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/kvm/vmx.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 449060ea1450..f1abe23da5d3 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -771,10 +771,9 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu) #endif #ifdef CONFIG_X86_64 - if (is_long_mode(&vmx->vcpu)) { - rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); + rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); + if (is_long_mode(&vmx->vcpu)) wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base); - } #endif for (i = 0; i < vmx->save_nmsrs; ++i) kvm_set_shared_msr(vmx->guest_msrs[i].index, @@ -789,11 +788,14 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) ++vmx->vcpu.stat.host_state_reload; vmx->host_state.loaded = 0; +#ifdef CONFIG_X86_64 + if (is_long_mode(&vmx->vcpu)) + rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base); +#endif if (vmx->host_state.gs_ldt_reload_needed) { kvm_load_ldt(vmx->host_state.ldt_sel); #ifdef CONFIG_X86_64 load_gs_index(vmx->host_state.gs_sel); - wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs); #else loadsegment(gs, vmx->host_state.gs_sel); #endif @@ -802,10 +804,7 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) loadsegment(fs, vmx->host_state.fs_sel); reload_tss(); #ifdef CONFIG_X86_64 - if (is_long_mode(&vmx->vcpu)) { - rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base); - wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); - } + wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); #endif load_gdt(&__get_cpu_var(host_gdt)); } -- cgit v1.2.3 From 44736f7cc1e6fa539449f1327b6e88323e96de57 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 28 Mar 2011 14:13:35 -0700 Subject: Relax si_code check in rt_sigqueueinfo and rt_tgsigqueueinfo [ upstream commit 243b422 ] Commit da48524eb206 ("Prevent rt_sigqueueinfo and rt_tgsigqueueinfo from spoofing the signal code") made the check on si_code too strict. There are several legitimate places where glibc wants to queue a negative si_code different from SI_QUEUE: - This was first noticed with glibc's aio implementation, which wants to queue a signal with si_code SI_ASYNCIO; the current kernel causes glibc's tst-aio4 test to fail because rt_sigqueueinfo() fails with EPERM. - Further examination of the glibc source shows that getaddrinfo_a() wants to use SI_ASYNCNL (which the kernel does not even define). The timer_create() fallback code wants to queue signals with SI_TIMER. As suggested by Oleg Nesterov , loosen the check to forbid only the problematic SI_TKILL case. Reported-by: Klaus Dittrich Acked-by: Julien Tinnes Signed-off-by: Andi Kleen Cc: Signed-off-by: Roland Dreier Signed-off-by: Linus Torvalds --- kernel/signal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/signal.c b/kernel/signal.c index cb0fff39f4e8..fdecae014340 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2412,7 +2412,7 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig, /* Not even root can pretend to send signals from the kernel. * Nor can they impersonate a kill()/tgkill(), which adds source info. */ - if (info.si_code != SI_QUEUE) { + if (info.si_code >= 0 || info.si_code == SI_TKILL) { /* We used to allow any < 0 si_code */ WARN_ON_ONCE(info.si_code < 0); return -EPERM; @@ -2432,7 +2432,7 @@ long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info) /* Not even root can pretend to send signals from the kernel. * Nor can they impersonate a kill()/tgkill(), which adds source info. */ - if (info->si_code != SI_QUEUE) { + if (info->si_code >= 0 || info->si_code == SI_TKILL) { /* We used to allow any < 0 si_code */ WARN_ON_ONCE(info->si_code < 0); return -EPERM; -- cgit v1.2.3 From cd854fa8669e98b116ff3863df4e708890edb6b4 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 31 Mar 2011 11:58:56 -0700 Subject: Release 2.6.35.12 Signed-off-by: Andi Kleen --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 78daa864f9fd..92b2538892af 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 35 -EXTRAVERSION = .11 +EXTRAVERSION = .12 NAME = Yokohama # *DOCUMENTATION* -- cgit v1.2.3 From 7c2141d484fbfa03af5f83602162d9576564121b Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Thu, 13 Jan 2011 15:45:41 -0800 Subject: mm: page allocator: adjust the per-cpu counter threshold when memory is low Upstream commit 88f5acf88ae6a9778f6d25d0d5d7ec2d57764a97 Commit aa45484 ("calculate a better estimate of NR_FREE_PAGES when memory is low") noted that watermarks were based on the vmstat NR_FREE_PAGES. To avoid synchronization overhead, these counters are maintained on a per-cpu basis and drained both periodically and when a threshold is above a threshold. On large CPU systems, the difference between the estimate and real value of NR_FREE_PAGES can be very high. The system can get into a case where pages are allocated far below the min watermark potentially causing livelock issues. The commit solved the problem by taking a better reading of NR_FREE_PAGES when memory was low. Unfortately, as reported by Shaohua Li this accurate reading can consume a large amount of CPU time on systems with many sockets due to cache line bouncing. This patch takes a different approach. For large machines where counter drift might be unsafe and while kswapd is awake, the per-cpu thresholds for the target pgdat are reduced to limit the level of drift to what should be a safe level. This incurs a performance penalty in heavy memory pressure by a factor that depends on the workload and the machine but the machine should function correctly without accidentally exhausting all memory on a node. There is an additional cost when kswapd wakes and sleeps but the event is not expected to be frequent - in Shaohua's test case, there was one recorded sleep and wake event at least. To ensure that kswapd wakes up, a safe version of zone_watermark_ok() is introduced that takes a more accurate reading of NR_FREE_PAGES when called from wakeup_kswapd, when deciding whether it is really safe to go back to sleep in sleeping_prematurely() and when deciding if a zone is really balanced or not in balance_pgdat(). We are still using an expensive function but limiting how often it is called. When the test case is reproduced, the time spent in the watermark functions is reduced. The following report is on the percentage of time spent cumulatively spent in the functions zone_nr_free_pages(), zone_watermark_ok(), __zone_watermark_ok(), zone_watermark_ok_safe(), zone_page_state_snapshot(), zone_page_state(). vanilla 11.6615% disable-threshold 0.2584% David said: : We had to pull aa454840 "mm: page allocator: calculate a better estimate : of NR_FREE_PAGES when memory is low and kswapd is awake" from 2.6.36 : internally because tests showed that it would cause the machine to stall : as the result of heavy kswapd activity. I merged it back with this fix as : it is pending in the -mm tree and it solves the issue we were seeing, so I : definitely think this should be pushed to -stable (and I would seriously : consider it for 2.6.37 inclusion even at this late date). Signed-off-by: Mel Gorman Signed-off-by: Andi Kleen Reported-by: Shaohua Li Reviewed-by: Christoph Lameter Tested-by: Nicolas Bareil Cc: David Rientjes Cc: Kyle McMartin Cc: [2.6.37.1, 2.6.36.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds backported from 88f5acf88ae6a9778f6d25d0d5d7ec2d57764a97 BugLink: http://bugs.launchpad.net/bugs/719446 Signed-off-by: Tim Gardner Signed-off-by: Andi Kleen --- include/linux/mmzone.h | 10 +++----- include/linux/vmstat.h | 5 ++++ mm/mmzone.c | 21 ---------------- mm/page_alloc.c | 35 ++++++++++++++++++++------ mm/vmscan.c | 25 +++++++++++-------- mm/vmstat.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 116 insertions(+), 48 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 8b2db3d65564..1e3d0b423f66 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -463,12 +463,6 @@ static inline int zone_is_oom_locked(const struct zone *zone) return test_bit(ZONE_OOM_LOCKED, &zone->flags); } -#ifdef CONFIG_SMP -unsigned long zone_nr_free_pages(struct zone *zone); -#else -#define zone_nr_free_pages(zone) zone_page_state(zone, NR_FREE_PAGES) -#endif /* CONFIG_SMP */ - /* * The "priority" of VM scanning is how much of the queues we will scan in one * go. A value of 12 for DEF_PRIORITY implies that we will scan 1/4096th of the @@ -668,7 +662,9 @@ void get_zone_counts(unsigned long *active, unsigned long *inactive, unsigned long *free); void build_all_zonelists(void *data); void wakeup_kswapd(struct zone *zone, int order); -int zone_watermark_ok(struct zone *z, int order, unsigned long mark, +bool zone_watermark_ok(struct zone *z, int order, unsigned long mark, + int classzone_idx, int alloc_flags); +bool zone_watermark_ok_safe(struct zone *z, int order, unsigned long mark, int classzone_idx, int alloc_flags); enum memmap_context { MEMMAP_EARLY, diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h index eaaea37b3b75..e4cc21cf5870 100644 --- a/include/linux/vmstat.h +++ b/include/linux/vmstat.h @@ -254,6 +254,8 @@ extern void dec_zone_state(struct zone *, enum zone_stat_item); extern void __dec_zone_state(struct zone *, enum zone_stat_item); void refresh_cpu_vm_stats(int); +void reduce_pgdat_percpu_threshold(pg_data_t *pgdat); +void restore_pgdat_percpu_threshold(pg_data_t *pgdat); #else /* CONFIG_SMP */ /* @@ -298,6 +300,9 @@ static inline void __dec_zone_page_state(struct page *page, #define dec_zone_page_state __dec_zone_page_state #define mod_zone_page_state __mod_zone_page_state +static inline void reduce_pgdat_percpu_threshold(pg_data_t *pgdat) { } +static inline void restore_pgdat_percpu_threshold(pg_data_t *pgdat) { } + static inline void refresh_cpu_vm_stats(int cpu) { } #endif diff --git a/mm/mmzone.c b/mm/mmzone.c index e35bfb82c855..f5b7d1760213 100644 --- a/mm/mmzone.c +++ b/mm/mmzone.c @@ -87,24 +87,3 @@ int memmap_valid_within(unsigned long pfn, return 1; } #endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */ - -#ifdef CONFIG_SMP -/* Called when a more accurate view of NR_FREE_PAGES is needed */ -unsigned long zone_nr_free_pages(struct zone *zone) -{ - unsigned long nr_free_pages = zone_page_state(zone, NR_FREE_PAGES); - - /* - * While kswapd is awake, it is considered the zone is under some - * memory pressure. Under pressure, there is a risk that - * per-cpu-counter-drift will allow the min watermark to be breached - * potentially causing a live-lock. While kswapd is awake and - * free pages are low, get a better estimate for free pages - */ - if (nr_free_pages < zone->percpu_drift_mark && - !waitqueue_active(&zone->zone_pgdat->kswapd_wait)) - return zone_page_state_snapshot(zone, NR_FREE_PAGES); - - return nr_free_pages; -} -#endif /* CONFIG_SMP */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2b085d51411c..68404aa8523d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1459,24 +1459,24 @@ static inline int should_fail_alloc_page(gfp_t gfp_mask, unsigned int order) #endif /* CONFIG_FAIL_PAGE_ALLOC */ /* - * Return 1 if free pages are above 'mark'. This takes into account the order + * Return true if free pages are above 'mark'. This takes into account the order * of the allocation. */ -int zone_watermark_ok(struct zone *z, int order, unsigned long mark, - int classzone_idx, int alloc_flags) +static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark, + int classzone_idx, int alloc_flags, long free_pages) { /* free_pages my go negative - that's OK */ long min = mark; - long free_pages = zone_nr_free_pages(z) - (1 << order) + 1; int o; + free_pages -= (1 << order) + 1; if (alloc_flags & ALLOC_HIGH) min -= min / 2; if (alloc_flags & ALLOC_HARDER) min -= min / 4; if (free_pages <= min + z->lowmem_reserve[classzone_idx]) - return 0; + return false; for (o = 0; o < order; o++) { /* At the next order, this order's pages become unavailable */ free_pages -= z->free_area[o].nr_free << o; @@ -1485,9 +1485,28 @@ int zone_watermark_ok(struct zone *z, int order, unsigned long mark, min >>= 1; if (free_pages <= min) - return 0; + return false; } - return 1; + return true; +} + +bool zone_watermark_ok(struct zone *z, int order, unsigned long mark, + int classzone_idx, int alloc_flags) +{ + return __zone_watermark_ok(z, order, mark, classzone_idx, alloc_flags, + zone_page_state(z, NR_FREE_PAGES)); +} + +bool zone_watermark_ok_safe(struct zone *z, int order, unsigned long mark, + int classzone_idx, int alloc_flags) +{ + long free_pages = zone_page_state(z, NR_FREE_PAGES); + + if (z->percpu_drift_mark && free_pages < z->percpu_drift_mark) + free_pages = zone_page_state_snapshot(z, NR_FREE_PAGES); + + return __zone_watermark_ok(z, order, mark, classzone_idx, alloc_flags, + free_pages); } #ifdef CONFIG_NUMA @@ -2430,7 +2449,7 @@ void show_free_areas(void) " all_unreclaimable? %s" "\n", zone->name, - K(zone_nr_free_pages(zone)), + K(zone_page_state(zone, NR_FREE_PAGES)), K(min_wmark_pages(zone)), K(low_wmark_pages(zone)), K(high_wmark_pages(zone)), diff --git a/mm/vmscan.c b/mm/vmscan.c index 975362619e19..22e56769e006 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2007,7 +2007,7 @@ static int sleeping_prematurely(pg_data_t *pgdat, int order, long remaining) if (zone->all_unreclaimable) continue; - if (!zone_watermark_ok(zone, order, high_wmark_pages(zone), + if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone), 0, 0)) return 1; } @@ -2104,7 +2104,7 @@ loop_again: shrink_active_list(SWAP_CLUSTER_MAX, zone, &sc, priority, 0); - if (!zone_watermark_ok(zone, order, + if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone), 0, 0)) { end_zone = i; break; @@ -2155,7 +2155,7 @@ loop_again: * We put equal pressure on every zone, unless one * zone has way too many pages free already. */ - if (!zone_watermark_ok(zone, order, + if (!zone_watermark_ok_safe(zone, order, 8*high_wmark_pages(zone), end_zone, 0)) shrink_zone(priority, zone, &sc); reclaim_state->reclaimed_slab = 0; @@ -2176,7 +2176,7 @@ loop_again: total_scanned > sc.nr_reclaimed + sc.nr_reclaimed / 2) sc.may_writepage = 1; - if (!zone_watermark_ok(zone, order, + if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone), end_zone, 0)) { all_zones_ok = 0; /* @@ -2184,7 +2184,7 @@ loop_again: * means that we have a GFP_ATOMIC allocation * failure risk. Hurry up! */ - if (!zone_watermark_ok(zone, order, + if (!zone_watermark_ok_safe(zone, order, min_wmark_pages(zone), end_zone, 0)) has_under_min_watermark_zone = 1; } @@ -2326,9 +2326,11 @@ static int kswapd(void *p) * premature sleep. If not, then go fully * to sleep until explicitly woken up */ - if (!sleeping_prematurely(pgdat, order, remaining)) + if (!sleeping_prematurely(pgdat, order, remaining)) { + restore_pgdat_percpu_threshold(pgdat); schedule(); - else { + reduce_pgdat_percpu_threshold(pgdat); + } else { if (remaining) count_vm_event(KSWAPD_LOW_WMARK_HIT_QUICKLY); else @@ -2364,15 +2366,16 @@ void wakeup_kswapd(struct zone *zone, int order) if (!populated_zone(zone)) return; - pgdat = zone->zone_pgdat; - if (zone_watermark_ok(zone, order, low_wmark_pages(zone), 0, 0)) + if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL)) return; + pgdat = zone->zone_pgdat; if (pgdat->kswapd_max_order < order) pgdat->kswapd_max_order = order; - if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL)) - return; if (!waitqueue_active(&pgdat->kswapd_wait)) return; + if (zone_watermark_ok_safe(zone, order, low_wmark_pages(zone), 0, 0)) + return; + wake_up_interruptible(&pgdat->kswapd_wait); } diff --git a/mm/vmstat.c b/mm/vmstat.c index 26d5716b1fce..41dc8cd96a68 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -81,6 +81,30 @@ EXPORT_SYMBOL(vm_stat); #ifdef CONFIG_SMP +static int calculate_pressure_threshold(struct zone *zone) +{ + int threshold; + int watermark_distance; + + /* + * As vmstats are not up to date, there is drift between the estimated + * and real values. For high thresholds and a high number of CPUs, it + * is possible for the min watermark to be breached while the estimated + * value looks fine. The pressure threshold is a reduced value such + * that even the maximum amount of drift will not accidentally breach + * the min watermark + */ + watermark_distance = low_wmark_pages(zone) - min_wmark_pages(zone); + threshold = max(1, (int)(watermark_distance / num_online_cpus())); + + /* + * Maximum threshold is 125 + */ + threshold = min(125, threshold); + + return threshold; +} + static int calculate_threshold(struct zone *zone) { int threshold; @@ -159,6 +183,48 @@ static void refresh_zone_stat_thresholds(void) } } +void reduce_pgdat_percpu_threshold(pg_data_t *pgdat) +{ + struct zone *zone; + int cpu; + int threshold; + int i; + + get_online_cpus(); + for (i = 0; i < pgdat->nr_zones; i++) { + zone = &pgdat->node_zones[i]; + if (!zone->percpu_drift_mark) + continue; + + threshold = calculate_pressure_threshold(zone); + for_each_online_cpu(cpu) + per_cpu_ptr(zone->pageset, cpu)->stat_threshold + = threshold; + } + put_online_cpus(); +} + +void restore_pgdat_percpu_threshold(pg_data_t *pgdat) +{ + struct zone *zone; + int cpu; + int threshold; + int i; + + get_online_cpus(); + for (i = 0; i < pgdat->nr_zones; i++) { + zone = &pgdat->node_zones[i]; + if (!zone->percpu_drift_mark) + continue; + + threshold = calculate_threshold(zone); + for_each_online_cpu(cpu) + per_cpu_ptr(zone->pageset, cpu)->stat_threshold + = threshold; + } + put_online_cpus(); +} + /* * For use when we know that interrupts are disabled. */ @@ -826,7 +892,7 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat, "\n scanned %lu" "\n spanned %lu" "\n present %lu", - zone_nr_free_pages(zone), + zone_page_state(zone, NR_FREE_PAGES), min_wmark_pages(zone), low_wmark_pages(zone), high_wmark_pages(zone), -- cgit v1.2.3 From e0026eb67a332b6ab0f2e61838aeba1b15604696 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 28 May 2010 15:08:22 -0700 Subject: qla2xxx: Make the FC port capability mutual exclusive. [ upstream commit b0cd579cde8ee0c7ed52239531ba09bcbc5b54c2 ] In case of both target and initiator capabilities reported by fc port, the fc port port capability is made mutualy exclusive with priority given for target capabilities. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley Acked-by: Madhuranath Iyengar Signed-off-by: Andi Kleen --- drivers/scsi/qla2xxx/qla_isr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index be3d8bed2ecf..f347ea4b4211 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1119,9 +1119,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, fcport->port_type = FCT_TARGET; if (iop[0] & BIT_8) fcport->flags |= FCF_FCP2_DEVICE; - } - if (iop[0] & BIT_5) + } else if (iop[0] & BIT_5) fcport->port_type = FCT_INITIATOR; + if (logio->io_parameter[7] || logio->io_parameter[8]) fcport->supported_classes |= FC_COS_CLASS2; if (logio->io_parameter[9] || logio->io_parameter[10]) -- cgit v1.2.3 From 92df499eee56047df6dcac34a743ee72ba3a82ef Mon Sep 17 00:00:00 2001 From: Arjan Mels Date: Tue, 5 Apr 2011 20:26:11 +0200 Subject: staging: usbip: bugfixes related to kthread conversion commit d2dd0b07c3e725d386d20294ec906f7ddef207fa upstream. When doing a usb port reset do a queued reset instead to prevent a deadlock: the reset will cause the driver to unbind, causing the usb_driver_lock_for_reset to stall. Signed-off-by: Arjan Mels Signed-off-by: Andi Kleen Cc: Takahiro Hirofuchi Cc: Max Vozeler Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/stub_rx.c | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c index 5972ae70e381..d497653c2a9b 100644 --- a/drivers/staging/usbip/stub_rx.c +++ b/drivers/staging/usbip/stub_rx.c @@ -170,33 +170,23 @@ static int tweak_set_configuration_cmd(struct urb *urb) static int tweak_reset_device_cmd(struct urb *urb) { - struct usb_ctrlrequest *req; - __u16 value; - __u16 index; - int ret; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - value = le16_to_cpu(req->wValue); - index = le16_to_cpu(req->wIndex); - - usbip_uinfo("reset_device (port %d) to %s\n", index, - dev_name(&urb->dev->dev)); + struct stub_priv *priv = (struct stub_priv *) urb->context; + struct stub_device *sdev = priv->sdev; - /* all interfaces should be owned by usbip driver, so just reset it. */ - ret = usb_lock_device_for_reset(urb->dev, NULL); - if (ret < 0) { - dev_err(&urb->dev->dev, "lock for reset\n"); - return ret; - } - - /* try to reset the device */ - ret = usb_reset_device(urb->dev); - if (ret < 0) - dev_err(&urb->dev->dev, "device reset\n"); + usbip_uinfo("reset_device %s\n", dev_name(&urb->dev->dev)); - usb_unlock_device(urb->dev); - - return ret; + /* + * usb_lock_device_for_reset caused a deadlock: it causes the driver + * to unbind. In the shutdown the rx thread is signalled to shut down + * but this thread is pending in the usb_lock_device_for_reset. + * + * Instead queue the reset. + * + * Unfortunatly an existing usbip connection will be dropped due to + * driver unbinding. + */ + usb_queue_reset_device(sdev->interface); + return 0; } /* -- cgit v1.2.3 From db898d0c5c493ce4177d5e1d3a953e079a56a24b Mon Sep 17 00:00:00 2001 From: Arjan Mels Date: Tue, 5 Apr 2011 20:26:38 +0200 Subject: staging: usbip: bugfix add number of packets for isochronous frames commit 1325f85fa49f57df034869de430f7c302ae23109 upstream. The number_of_packets was not transmitted for RET_SUBMIT packets. The linux client used the stored number_of_packet from the submitted request. The windows userland client does not do this however and needs to know the number_of_packets to determine the size of the transmission. Signed-off-by: Arjan Mels Signed-off-by: Andi Kleen Cc: Takahiro Hirofuchi Cc: Max Vozeler Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/usbip_common.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c index 6a499f0eb594..8497f6d5819b 100644 --- a/drivers/staging/usbip/usbip_common.c +++ b/drivers/staging/usbip/usbip_common.c @@ -334,10 +334,11 @@ void usbip_dump_header(struct usbip_header *pdu) usbip_udbg("CMD_UNLINK: seq %u\n", pdu->u.cmd_unlink.seqnum); break; case USBIP_RET_SUBMIT: - usbip_udbg("RET_SUBMIT: st %d al %u sf %d ec %d\n", + usbip_udbg("RET_SUBMIT: st %d al %u sf %d #p %d ec %d\n", pdu->u.ret_submit.status, pdu->u.ret_submit.actual_length, pdu->u.ret_submit.start_frame, + pdu->u.ret_submit.number_of_packets, pdu->u.ret_submit.error_count); case USBIP_RET_UNLINK: usbip_udbg("RET_UNLINK: status %d\n", pdu->u.ret_unlink.status); @@ -625,6 +626,7 @@ static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb, rpdu->status = urb->status; rpdu->actual_length = urb->actual_length; rpdu->start_frame = urb->start_frame; + rpdu->number_of_packets = urb->number_of_packets; rpdu->error_count = urb->error_count; } else { /* vhci_rx.c */ @@ -632,6 +634,7 @@ static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb, urb->status = rpdu->status; urb->actual_length = rpdu->actual_length; urb->start_frame = rpdu->start_frame; + urb->number_of_packets = rpdu->number_of_packets; urb->error_count = rpdu->error_count; } } @@ -700,11 +703,13 @@ static void correct_endian_ret_submit(struct usbip_header_ret_submit *pdu, cpu_to_be32s(&pdu->status); cpu_to_be32s(&pdu->actual_length); cpu_to_be32s(&pdu->start_frame); + cpu_to_be32s(&pdu->number_of_packets); cpu_to_be32s(&pdu->error_count); } else { be32_to_cpus(&pdu->status); be32_to_cpus(&pdu->actual_length); be32_to_cpus(&pdu->start_frame); + cpu_to_be32s(&pdu->number_of_packets); be32_to_cpus(&pdu->error_count); } } -- cgit v1.2.3 From dfc75cfe82f7961feae07838cb832853d7433543 Mon Sep 17 00:00:00 2001 From: Arjan Mels Date: Tue, 5 Apr 2011 20:26:59 +0200 Subject: staging: usbip: bugfix for isochronous packets and optimization commit 28276a28d8b3cd19f4449991faad4945fe557656 upstream. For isochronous packets the actual_length is the sum of the actual length of each of the packets, however between the packets might be padding, so it is not sufficient to just send the first actual_length bytes of the buffer. To fix this and simultanesouly optimize the bandwidth the content of the isochronous packets are send without the padding, the padding is restored on the receiving end. Signed-off-by: Arjan Mels Signed-off-by: Andi Kleen Cc: Takahiro Hirofuchi Cc: Max Vozeler Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/stub_tx.c | 74 +++++++++++++++++++++++++++++------- drivers/staging/usbip/usbip_common.c | 57 +++++++++++++++++++++++++++ drivers/staging/usbip/usbip_common.h | 2 + drivers/staging/usbip/vhci_rx.c | 3 ++ 4 files changed, 122 insertions(+), 14 deletions(-) diff --git a/drivers/staging/usbip/stub_tx.c b/drivers/staging/usbip/stub_tx.c index d7136e2c86fa..b7a493c1df46 100644 --- a/drivers/staging/usbip/stub_tx.c +++ b/drivers/staging/usbip/stub_tx.c @@ -169,7 +169,6 @@ static int stub_send_ret_submit(struct stub_device *sdev) struct stub_priv *priv, *tmp; struct msghdr msg; - struct kvec iov[3]; size_t txsize; size_t total_size = 0; @@ -179,28 +178,73 @@ static int stub_send_ret_submit(struct stub_device *sdev) struct urb *urb = priv->urb; struct usbip_header pdu_header; void *iso_buffer = NULL; + struct kvec *iov = NULL; + int iovnum = 0; txsize = 0; memset(&pdu_header, 0, sizeof(pdu_header)); memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - usbip_dbg_stub_tx("setup txdata urb %p\n", urb); + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) + iovnum = 2 + urb->number_of_packets; + else + iovnum = 2; + + iov = kzalloc(iovnum * sizeof(struct kvec), GFP_KERNEL); + if (!iov) { + usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_MALLOC); + return -1; + } + + iovnum = 0; /* 1. setup usbip_header */ setup_ret_submit_pdu(&pdu_header, urb); + usbip_dbg_stub_tx("setup txdata seqnum: %d urb: %p\n", + pdu_header.base.seqnum, urb); + /*usbip_dump_header(pdu_header);*/ usbip_header_correct_endian(&pdu_header, 1); - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); + iov[iovnum].iov_base = &pdu_header; + iov[iovnum].iov_len = sizeof(pdu_header); + iovnum++; txsize += sizeof(pdu_header); /* 2. setup transfer buffer */ - if (usb_pipein(urb->pipe) && urb->actual_length > 0) { - iov[1].iov_base = urb->transfer_buffer; - iov[1].iov_len = urb->actual_length; + if (usb_pipein(urb->pipe) && + usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS && + urb->actual_length > 0) { + iov[iovnum].iov_base = urb->transfer_buffer; + iov[iovnum].iov_len = urb->actual_length; + iovnum++; txsize += urb->actual_length; + } else if (usb_pipein(urb->pipe) && + usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { + /* + * For isochronous packets: actual length is the sum of + * the actual length of the individual, packets, but as + * the packet offsets are not changed there will be + * padding between the packets. To optimally use the + * bandwidth the padding is not transmitted. + */ + + int i; + for (i = 0; i < urb->number_of_packets; i++) { + iov[iovnum].iov_base = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + iov[iovnum].iov_len = urb->iso_frame_desc[i].actual_length; + iovnum++; + txsize += urb->iso_frame_desc[i].actual_length; + } + + if (txsize != sizeof(pdu_header) + urb->actual_length) { + dev_err(&sdev->interface->dev, + "actual length of urb (%d) does not match iso packet sizes (%d)\n", + urb->actual_length, txsize-sizeof(pdu_header)); + kfree(iov); + usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP); + return -1; + } } /* 3. setup iso_packet_descriptor */ @@ -211,32 +255,34 @@ static int stub_send_ret_submit(struct stub_device *sdev) if (!iso_buffer) { usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_MALLOC); + kfree(iov); return -1; } - iov[2].iov_base = iso_buffer; - iov[2].iov_len = len; + iov[iovnum].iov_base = iso_buffer; + iov[iovnum].iov_len = len; txsize += len; + iovnum++; } - ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov, - 3, txsize); + ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, + iov, iovnum, txsize); if (ret != txsize) { dev_err(&sdev->interface->dev, "sendmsg failed!, retval %d for %zd\n", ret, txsize); + kfree(iov); kfree(iso_buffer); usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP); return -1; } + kfree(iov); kfree(iso_buffer); - usbip_dbg_stub_tx("send txdata\n"); total_size += txsize; } - spin_lock_irqsave(&sdev->priv_lock, flags); list_for_each_entry_safe(priv, tmp, &sdev->priv_free, list) { diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c index 8497f6d5819b..c141eef47257 100644 --- a/drivers/staging/usbip/usbip_common.c +++ b/drivers/staging/usbip/usbip_common.c @@ -835,6 +835,7 @@ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb) int size = np * sizeof(*iso); int i; int ret; + int total_length = 0; if (!usb_pipeisoc(urb->pipe)) return 0; @@ -864,19 +865,75 @@ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb) return -EPIPE; } + for (i = 0; i < np; i++) { iso = buff + (i * sizeof(*iso)); usbip_iso_pakcet_correct_endian(iso, 0); usbip_pack_iso(iso, &urb->iso_frame_desc[i], 0); + total_length += urb->iso_frame_desc[i].actual_length; } kfree(buff); + if (total_length != urb->actual_length) { + dev_err(&urb->dev->dev, + "total length of iso packets (%d) not equal to actual length of buffer (%d)\n", + total_length, urb->actual_length); + + if (ud->side == USBIP_STUB) + usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); + else + usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); + + return -EPIPE; + } + return ret; } EXPORT_SYMBOL_GPL(usbip_recv_iso); +/* + * This functions restores the padding which was removed for optimizing + * the bandwidth during transfer over tcp/ip + * + * buffer and iso packets need to be stored and be in propeper endian in urb + * before calling this function + */ +int usbip_pad_iso(struct usbip_device *ud, struct urb *urb) +{ + int np = urb->number_of_packets; + int i; + int ret; + int actualoffset = urb->actual_length; + + if (!usb_pipeisoc(urb->pipe)) + return 0; + + /* if no packets or length of data is 0, then nothing to unpack */ + if (np == 0 || urb->actual_length == 0) + return 0; + + /* + * if actual_length is transfer_buffer_length then no padding is + * present. + */ + if (urb->actual_length == urb->transfer_buffer_length) + return 0; + + /* + * loop over all packets from last to first (to prevent overwritting + * memory when padding) and move them into the proper place + */ + for (i = np-1; i > 0; i--) { + actualoffset -= urb->iso_frame_desc[i].actual_length; + memmove(urb->transfer_buffer + urb->iso_frame_desc[i].offset, + urb->transfer_buffer + actualoffset, + urb->iso_frame_desc[i].actual_length); + } + return ret; +} +EXPORT_SYMBOL_GPL(usbip_pad_iso); /* some members of urb must be substituted before. */ int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb) diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h index e1bbd1287e28..af6903c37e5a 100644 --- a/drivers/staging/usbip/usbip_common.h +++ b/drivers/staging/usbip/usbip_common.h @@ -393,6 +393,8 @@ void usbip_header_correct_endian(struct usbip_header *pdu, int send); int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb); /* some members of urb must be substituted before. */ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb); +/* some members of urb must be substituted before. */ +int usbip_pad_iso(struct usbip_device *ud, struct urb *urb); void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen); diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c index bdbedd256903..a1ac1b8b1916 100644 --- a/drivers/staging/usbip/vhci_rx.c +++ b/drivers/staging/usbip/vhci_rx.c @@ -99,6 +99,9 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, if (usbip_recv_iso(ud, urb) < 0) return; + /* restore the padding in iso packets */ + if (usbip_pad_iso(ud, urb) < 0) + return; if (usbip_dbg_flag_vhci_rx) usbip_dump_urb(urb); -- cgit v1.2.3 From fd5d4740a543f457f787a7760a309350a49bb8c6 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Wed, 6 Apr 2011 15:18:00 -0700 Subject: staging: hv: Fix GARP not sent after Quick Migration commit c996edcf1c451b81740abbcca5257ed7e353fcc6 upstream. After Quick Migration, the network is not immediately operational in the current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, I added another netif_notify_peers() into a scheduled work, otherwise GARP packet will not be sent after quick migration, and cause network disconnection. Thanks to Mike Surcouf for reporting the bug and testing the patch. Reported-by: Mike Surcouf Tested-by: Mike Surcouf Signed-off-by: Haiyang Zhang Signed-off-by: Hank Janssen Signed-off-by: Abhishek Kane Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/hv/netvsc_drv.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index a2b8c6d1f2e8..f1a7402f5d5b 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -46,6 +46,7 @@ struct net_device_context { /* point back to our device context */ struct vm_device *device_ctx; unsigned long avail; + struct work_struct work; }; struct netvsc_driver_context { @@ -237,6 +238,7 @@ static void netvsc_linkstatus_callback(struct hv_device *device_obj, { struct vm_device *device_ctx = to_vm_device(device_obj); struct net_device *net = dev_get_drvdata(&device_ctx->device); + struct net_device_context *ndev_ctx; DPRINT_ENTER(NETVSC_DRV); @@ -250,6 +252,8 @@ static void netvsc_linkstatus_callback(struct hv_device *device_obj, netif_carrier_on(net); netif_wake_queue(net); netif_notify_peers(net); + ndev_ctx = netdev_priv(net); + schedule_work(&ndev_ctx->work); } else { netif_carrier_off(net); netif_stop_queue(net); @@ -354,6 +358,25 @@ static const struct net_device_ops device_ops = { .ndo_set_mac_address = eth_mac_addr, }; +/* + * Send GARP packet to network peers after migrations. + * After Quick Migration, the network is not immediately operational in the + * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add + * another netif_notify_peers() into a scheduled work, otherwise GARP packet + * will not be sent after quick migration, and cause network disconnection. + */ +static void netvsc_send_garp(struct work_struct *w) +{ + struct net_device_context *ndev_ctx; + struct net_device *net; + + msleep(20); + ndev_ctx = container_of(w, struct net_device_context, work); + net = dev_get_drvdata(&ndev_ctx->device_ctx->device); + netif_notify_peers(net); +} + + static int netvsc_probe(struct device *device) { struct driver_context *driver_ctx = @@ -385,6 +408,7 @@ static int netvsc_probe(struct device *device) net_device_ctx->device_ctx = device_ctx; net_device_ctx->avail = ring_size; dev_set_drvdata(device, net); + INIT_WORK(&net_device_ctx->work, netvsc_send_garp); /* Notify the netvsc driver of the new device */ ret = net_drv_obj->Base.OnDeviceAdd(device_obj, &device_info); -- cgit v1.2.3 From db9fb5db749de2109d9312929c6e2f70b2055f89 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Mon, 21 Mar 2011 14:41:37 +0100 Subject: staging: hv: use sync_bitops when interacting with the hypervisor commit 22356585712d1ff08fbfed152edd8b386873b238 upstream. Locking is required when tweaking bits located in a shared page, use the sync_ version of bitops. Without this change vmbus_on_event() will miss events and as a result, vmbus_isr() will not schedule the receive tasklet. [Backported to 2.6.32 stable kernel by Haiyang Zhang ] Signed-off-by: Olaf Hering Acked-by: Haiyang Zhang Acked-by: Hank Janssen Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/hv/channel.c | 8 ++++---- drivers/staging/hv/connection.c | 6 ++++-- drivers/staging/hv/vmbus.c | 2 +- drivers/staging/hv/vmbus_private.h | 1 + 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c index f047c5a7f64c..8955d6a4fb22 100644 --- a/drivers/staging/hv/channel.c +++ b/drivers/staging/hv/channel.c @@ -78,14 +78,14 @@ static void VmbusChannelSetEvent(struct vmbus_channel *Channel) if (Channel->OfferMsg.MonitorAllocated) { /* Each u32 represents 32 channels */ - set_bit(Channel->OfferMsg.ChildRelId & 31, + sync_set_bit(Channel->OfferMsg.ChildRelId & 31, (unsigned long *) gVmbusConnection.SendInterruptPage + (Channel->OfferMsg.ChildRelId >> 5)); monitorPage = gVmbusConnection.MonitorPages; monitorPage++; /* Get the child to parent monitor page */ - set_bit(Channel->MonitorBit, + sync_set_bit(Channel->MonitorBit, (unsigned long *)&monitorPage->TriggerGroup [Channel->MonitorGroup].Pending); @@ -105,7 +105,7 @@ static void VmbusChannelClearEvent(struct vmbus_channel *channel) if (Channel->OfferMsg.MonitorAllocated) { /* Each u32 represents 32 channels */ - clear_bit(Channel->OfferMsg.ChildRelId & 31, + sync_clear_bit(Channel->OfferMsg.ChildRelId & 31, (unsigned long *)gVmbusConnection.SendInterruptPage + (Channel->OfferMsg.ChildRelId >> 5)); @@ -113,7 +113,7 @@ static void VmbusChannelClearEvent(struct vmbus_channel *channel) (struct hv_monitor_page *)gVmbusConnection.MonitorPages; monitorPage++; /* Get the child to parent monitor page */ - clear_bit(Channel->MonitorBit, + sync_clear_bit(Channel->MonitorBit, (unsigned long *)&monitorPage->TriggerGroup [Channel->MonitorGroup].Pending); } diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c index e8824dadffc3..d80a9f319d14 100644 --- a/drivers/staging/hv/connection.c +++ b/drivers/staging/hv/connection.c @@ -292,7 +292,9 @@ void VmbusOnEvents(void) for (dword = 0; dword < maxdword; dword++) { if (recvInterruptPage[dword]) { for (bit = 0; bit < 32; bit++) { - if (test_and_clear_bit(bit, (unsigned long *)&recvInterruptPage[dword])) { + if (sync_test_and_clear_bit(bit, + (unsigned long *) + &recvInterruptPage[dword])) { relid = (dword << 5) + bit; DPRINT_DBG(VMBUS, "event detected for relid - %d", relid); @@ -337,7 +339,7 @@ int VmbusSetEvent(u32 childRelId) DPRINT_ENTER(VMBUS); /* Each u32 represents 32 channels */ - set_bit(childRelId & 31, + sync_set_bit(childRelId & 31, (unsigned long *)gVmbusConnection.SendInterruptPage + (childRelId >> 5)); diff --git a/drivers/staging/hv/vmbus.c b/drivers/staging/hv/vmbus.c index 007543bdb410..08a0c594de27 100644 --- a/drivers/staging/hv/vmbus.c +++ b/drivers/staging/hv/vmbus.c @@ -254,7 +254,7 @@ static int VmbusOnISR(struct hv_driver *drv) event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; /* Since we are a child, we only need to check bit 0 */ - if (test_and_clear_bit(0, (unsigned long *) &event->Flags32[0])) { + if (sync_test_and_clear_bit(0, (unsigned long *) &event->Flags32[0])) { DPRINT_DBG(VMBUS, "received event %d", event->Flags32[0]); ret |= 0x2; } diff --git a/drivers/staging/hv/vmbus_private.h b/drivers/staging/hv/vmbus_private.h index 588c667a7f6b..90d58dd7166e 100644 --- a/drivers/staging/hv/vmbus_private.h +++ b/drivers/staging/hv/vmbus_private.h @@ -32,6 +32,7 @@ #include "channel_interface.h" #include "ring_buffer.h" #include +#include /* -- cgit v1.2.3 From f3373d71e3cbda31c253a8be1956de17ad089bb6 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Mon, 14 Feb 2011 13:45:28 +0000 Subject: xfs: prevent leaking uninitialized stack memory in FSGEOMETRY_V1 commit c4d0c3b097f7584772316ee4d64a09fe0e4ddfca upstream. The FSGEOMETRY_V1 ioctl (and its compat equivalent) calls out to xfs_fs_geometry() with a version number of 3. This code path does not fill in the logsunit member of the passed xfs_fsop_geom_t, leading to the leaking of four bytes of uninitialized stack data to potentially unprivileged callers. v2 switches to memset() to avoid future issues if structure members change, on suggestion of Dave Chinner. Signed-off-by: Dan Rosenberg Signed-off-by: Andi Kleen Reviewed-by: Eugene Teo Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_fsops.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 37a6f62c57b6..4e7f02b22d1d 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -57,6 +57,9 @@ xfs_fs_geometry( xfs_fsop_geom_t *geo, int new_version) { + + memset(geo, 0, sizeof(*geo)); + geo->blocksize = mp->m_sb.sb_blocksize; geo->rtextsize = mp->m_sb.sb_rextsize; geo->agblocks = mp->m_sb.sb_agblocks; -- cgit v1.2.3 From 44b722fa1d1fdaecdf6fce55c26f90a98ea4b1d2 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Sun, 20 Mar 2011 15:32:06 +0000 Subject: irda: validate peer name and attribute lengths commit d370af0ef7951188daeb15bae75db7ba57c67846 upstream. Length fields provided by a peer for names and attributes may be longer than the destination array sizes. Validate lengths to prevent stack buffer overflows. Signed-off-by: Dan Rosenberg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/irda/iriap.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/irda/iriap.c b/net/irda/iriap.c index 5b743bdd89ba..36477538cea8 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c @@ -656,10 +656,16 @@ static void iriap_getvaluebyclass_indication(struct iriap_cb *self, n = 1; name_len = fp[n++]; + + IRDA_ASSERT(name_len < IAS_MAX_CLASSNAME + 1, return;); + memcpy(name, fp+n, name_len); n+=name_len; name[name_len] = '\0'; attr_len = fp[n++]; + + IRDA_ASSERT(attr_len < IAS_MAX_ATTRIBNAME + 1, return;); + memcpy(attr, fp+n, attr_len); n+=attr_len; attr[attr_len] = '\0'; -- cgit v1.2.3 From 0b03d0985f309d5f65498220a01d7c2b4bb77661 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Sat, 19 Mar 2011 20:14:30 +0000 Subject: irda: prevent heap corruption on invalid nickname commit d50e7e3604778bfc2dc40f440e0742dbae399d54 upstream. Invalid nicknames containing only spaces will result in an underflow in a memcpy size calculation, subsequently destroying the heap and panicking. v2 also catches the case where the provided nickname is longer than the buffer size, which can result in controllable heap corruption. Signed-off-by: Dan Rosenberg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/irda/irnet/irnet_ppp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c index 6a1a202710c5..ab5bee29dc33 100644 --- a/net/irda/irnet/irnet_ppp.c +++ b/net/irda/irnet/irnet_ppp.c @@ -106,6 +106,9 @@ irnet_ctrl_write(irnet_socket * ap, while(isspace(start[length - 1])) length--; + DABORT(length < 5 || length > NICKNAME_MAX_LEN + 5, + -EINVAL, CTRL_ERROR, "Invalid nickname.\n"); + /* Copy the name for later reuse */ memcpy(ap->rname, start + 5, length - 5); ap->rname[length - 5] = '\0'; -- cgit v1.2.3 From 61b4a6c0ab467bb30931018fc620e93c5602c96b Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Sun, 27 Mar 2011 22:50:49 +0900 Subject: nilfs2: fix data loss in mmap page write for hole blocks commit 34094537943113467faee98fe67c8a3d3f9a0a8b upstream. From the result of a function test of mmap, mmap write to shared pages turned out to be broken for hole blocks. It doesn't write out filled blocks and the data will be lost after umount. This is due to a bug that the target file is not queued for log writer when filling hole blocks. Also, nilfs_page_mkwrite function exits normal code path even after successfully filled hole blocks due to a change of block_page_mkwrite function; just after nilfs was merged into the mainline, block_page_mkwrite() started to return VM_FAULT_LOCKED instead of zero by the patch "mm: close page_mkwrite races" (commit: b827e496c893de0c). The current nilfs_page_mkwrite() is not handling this value properly. This corrects nilfs_page_mkwrite() and will resolve the data loss problem in mmap write. [This should be applied to every kernel since 2.6.30 but a fix is needed for 2.6.37 and prior kernels] Signed-off-by: Ryusuke Konishi Signed-off-by: Andi Kleen Tested-by: Ryusuke Konishi Signed-off-by: Greg Kroah-Hartman --- fs/nilfs2/file.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c index c9a30d7ff6fc..d9d5d8141b4f 100644 --- a/fs/nilfs2/file.c +++ b/fs/nilfs2/file.c @@ -72,10 +72,9 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) /* * check to see if the page is mapped already (no holes) */ - if (PageMappedToDisk(page)) { - unlock_page(page); + if (PageMappedToDisk(page)) goto mapped; - } + if (page_has_buffers(page)) { struct buffer_head *bh, *head; int fully_mapped = 1; @@ -90,7 +89,6 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) if (fully_mapped) { SetPageMappedToDisk(page); - unlock_page(page); goto mapped; } } @@ -105,16 +103,18 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) return VM_FAULT_SIGBUS; ret = block_page_mkwrite(vma, vmf, nilfs_get_block); - if (unlikely(ret)) { + if (ret != VM_FAULT_LOCKED) { nilfs_transaction_abort(inode->i_sb); return ret; } + nilfs_set_file_dirty(NILFS_SB(inode->i_sb), inode, + 1 << (PAGE_SHIFT - inode->i_blkbits)); nilfs_transaction_commit(inode->i_sb); mapped: SetPageChecked(page); wait_on_page_writeback(page); - return 0; + return VM_FAULT_LOCKED; } static const struct vm_operations_struct nilfs_file_vm_ops = { -- cgit v1.2.3 From 5f46532ee26f42500aa79df246f3ccbef013c6f8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 23 Mar 2011 20:45:40 +0000 Subject: ASoC: Explicitly say registerless widgets have no register commit 0ca03cd7d0fa3bfbd56958136a10f19733c4ce12 upstream. This stops code that handles widgets generically from attempting to access registers for these widgets. Signed-off-by: Mark Brown Acked-by: Liam Girdwood Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/sound/soc-dapm.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 66ff4c124dbd..f9021419bed3 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -46,25 +46,25 @@ /* platform domain */ #define SND_SOC_DAPM_INPUT(wname) \ { .id = snd_soc_dapm_input, .name = wname, .kcontrols = NULL, \ - .num_kcontrols = 0} + .num_kcontrols = 0, .reg = SND_SOC_NOPM } #define SND_SOC_DAPM_OUTPUT(wname) \ { .id = snd_soc_dapm_output, .name = wname, .kcontrols = NULL, \ - .num_kcontrols = 0} + .num_kcontrols = 0, .reg = SND_SOC_NOPM } #define SND_SOC_DAPM_MIC(wname, wevent) \ { .id = snd_soc_dapm_mic, .name = wname, .kcontrols = NULL, \ - .num_kcontrols = 0, .event = wevent, \ + .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD} #define SND_SOC_DAPM_HP(wname, wevent) \ { .id = snd_soc_dapm_hp, .name = wname, .kcontrols = NULL, \ - .num_kcontrols = 0, .event = wevent, \ + .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD} #define SND_SOC_DAPM_SPK(wname, wevent) \ { .id = snd_soc_dapm_spk, .name = wname, .kcontrols = NULL, \ - .num_kcontrols = 0, .event = wevent, \ + .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD} #define SND_SOC_DAPM_LINE(wname, wevent) \ { .id = snd_soc_dapm_line, .name = wname, .kcontrols = NULL, \ - .num_kcontrols = 0, .event = wevent, \ + .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD} /* path domain */ @@ -161,11 +161,11 @@ /* events that are pre and post DAPM */ #define SND_SOC_DAPM_PRE(wname, wevent) \ { .id = snd_soc_dapm_pre, .name = wname, .kcontrols = NULL, \ - .num_kcontrols = 0, .event = wevent, \ + .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD} #define SND_SOC_DAPM_POST(wname, wevent) \ { .id = snd_soc_dapm_post, .name = wname, .kcontrols = NULL, \ - .num_kcontrols = 0, .event = wevent, \ + .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD} /* stream domain */ -- cgit v1.2.3 From b656c2b755012f488d2705d095db10854a2d803f Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 30 Mar 2011 08:24:25 +0200 Subject: ALSA: ens1371: fix Creative Ectiva support commit 6ebb8a4a43e34f999ab36f27f972f3cd751cda4f upstream. To make the EV1938 chip work, add a magic bit and an extra delay. Signed-off-by: Clemens Ladisch Signed-off-by: Andi Kleen Tested-by: Tino Schmidt Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/ens1370.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index c7fba5379813..d6a40e215965 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -229,6 +229,7 @@ MODULE_PARM_DESC(lineio, "Line In to Rear Out (0 = auto, 1 = force)."); #define ES_REG_1371_CODEC 0x14 /* W/R: Codec Read/Write register address */ #define ES_1371_CODEC_RDY (1<<31) /* codec ready */ #define ES_1371_CODEC_WIP (1<<30) /* codec register access in progress */ +#define EV_1938_CODEC_MAGIC (1<<26) #define ES_1371_CODEC_PIRD (1<<23) /* codec read/write select register */ #define ES_1371_CODEC_WRITE(a,d) ((((a)&0x7f)<<16)|(((d)&0xffff)<<0)) #define ES_1371_CODEC_READS(a) ((((a)&0x7f)<<16)|ES_1371_CODEC_PIRD) @@ -603,12 +604,18 @@ static void snd_es1370_codec_write(struct snd_ak4531 *ak4531, #ifdef CHIP1371 +static inline bool is_ev1938(struct ensoniq *ensoniq) +{ + return ensoniq->pci->device == 0x8938; +} + static void snd_es1371_codec_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) { struct ensoniq *ensoniq = ac97->private_data; - unsigned int t, x; + unsigned int t, x, flag; + flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0; mutex_lock(&ensoniq->src_mutex); for (t = 0; t < POLL_COUNT; t++) { if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) { @@ -630,7 +637,8 @@ static void snd_es1371_codec_write(struct snd_ac97 *ac97, 0x00010000) break; } - outl(ES_1371_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1371_CODEC)); + outl(ES_1371_CODEC_WRITE(reg, val) | flag, + ES_REG(ensoniq, 1371_CODEC)); /* restore SRC reg */ snd_es1371_wait_src_ready(ensoniq); outl(x, ES_REG(ensoniq, 1371_SMPRATE)); @@ -647,8 +655,9 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97, unsigned short reg) { struct ensoniq *ensoniq = ac97->private_data; - unsigned int t, x, fail = 0; + unsigned int t, x, flag, fail = 0; + flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0; __again: mutex_lock(&ensoniq->src_mutex); for (t = 0; t < POLL_COUNT; t++) { @@ -671,7 +680,8 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97, 0x00010000) break; } - outl(ES_1371_CODEC_READS(reg), ES_REG(ensoniq, 1371_CODEC)); + outl(ES_1371_CODEC_READS(reg) | flag, + ES_REG(ensoniq, 1371_CODEC)); /* restore SRC reg */ snd_es1371_wait_src_ready(ensoniq); outl(x, ES_REG(ensoniq, 1371_SMPRATE)); @@ -683,6 +693,11 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97, /* now wait for the stinkin' data (RDY) */ for (t = 0; t < POLL_COUNT; t++) { if ((x = inl(ES_REG(ensoniq, 1371_CODEC))) & ES_1371_CODEC_RDY) { + if (is_ev1938(ensoniq)) { + for (t = 0; t < 100; t++) + inl(ES_REG(ensoniq, CONTROL)); + x = inl(ES_REG(ensoniq, 1371_CODEC)); + } mutex_unlock(&ensoniq->src_mutex); return ES_1371_CODEC_READ(x); } -- cgit v1.2.3 From 18569f1467745ca8ebe929ecc43046ab71fd01a5 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Sat, 19 Mar 2011 20:43:43 +0000 Subject: ROSE: prevent heap corruption with bad facilities commit be20250c13f88375345ad99950190685eda51eb8 upstream. When parsing the FAC_NATIONAL_DIGIS facilities field, it's possible for a remote host to provide more digipeaters than expected, resulting in heap corruption. Check against ROSE_MAX_DIGIS to prevent overflows, and abort facilities parsing on failure. Additionally, when parsing the FAC_CCITT_DEST_NSAP and FAC_CCITT_SRC_NSAP facilities fields, a remote host can provide a length of less than 10, resulting in an underflow in a memcpy size, causing a kernel panic due to massive heap corruption. A length of greater than 20 results in a stack overflow of the callsign array. Abort facilities parsing on these invalid length values. Signed-off-by: Dan Rosenberg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/rose/rose_subr.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index 1734abba26a2..174d51c9ce37 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c @@ -290,10 +290,15 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct * facilities->source_ndigis = 0; facilities->dest_ndigis = 0; for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) { - if (pt[6] & AX25_HBIT) + if (pt[6] & AX25_HBIT) { + if (facilities->dest_ndigis >= ROSE_MAX_DIGIS) + return -1; memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN); - else + } else { + if (facilities->source_ndigis >= ROSE_MAX_DIGIS) + return -1; memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN); + } } } p += l + 2; @@ -333,6 +338,11 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac case 0xC0: l = p[1]; + + /* Prevent overflows*/ + if (l < 10 || l > 20) + return -1; + if (*p == FAC_CCITT_DEST_NSAP) { memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); memcpy(callsign, p + 12, l - 10); @@ -373,12 +383,16 @@ int rose_parse_facilities(unsigned char *p, switch (*p) { case FAC_NATIONAL: /* National */ len = rose_parse_national(p + 1, facilities, facilities_len - 1); + if (len < 0) + return 0; facilities_len -= len + 1; p += len + 1; break; case FAC_CCITT: /* CCITT */ len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1); + if (len < 0) + return 0; facilities_len -= len + 1; p += len + 1; break; -- cgit v1.2.3 From f86c63dd724d6779a6b193206d31008e0dc53c12 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 28 Mar 2011 02:01:25 +0000 Subject: Btrfs: Fix uninitialized root flags for subvolumes commit 08fe4db170b4193603d9d31f40ebaf652d07ac9c upstream. root_item->flags and root_item->byte_limit are not initialized when a subvolume is created. This bug is not revealed until we added readonly snapshot support - now you mount a btrfs filesystem and you may find the subvolumes in it are readonly. To work around this problem, we steal a bit from root_item->inode_item->flags, and use it to indicate if those fields have been properly initialized. When we read a tree root from disk, we check if the bit is set, and if not we'll set the flag and initialize the two fields of the root item. Reported-by: Andreas Philipp Signed-off-by: Li Zefan Signed-off-by: Andi Kleen Tested-by: Andreas Philipp Signed-off-by: Chris Mason Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/ctree.h | 4 ++++ fs/btrfs/disk-io.c | 4 +++- fs/btrfs/ioctl.c | 4 ++++ fs/btrfs/root-tree.c | 18 ++++++++++++++++++ fs/btrfs/transaction.c | 1 + 5 files changed, 30 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 29c20092847e..e40aab413dfe 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1212,6 +1212,8 @@ struct btrfs_root { #define BTRFS_INODE_NOATIME (1 << 9) #define BTRFS_INODE_DIRSYNC (1 << 10) +#define BTRFS_INODE_ROOT_ITEM_INIT (1 << 31) + /* some macros to generate set/get funcs for the struct fields. This * assumes there is a lefoo_to_cpu for every type, so lets make a simple * one for u8: @@ -2239,6 +2241,8 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid); int btrfs_find_orphan_roots(struct btrfs_root *tree_root); int btrfs_set_root_node(struct btrfs_root_item *item, struct extent_buffer *node); +void btrfs_check_and_init_root_item(struct btrfs_root_item *item); + /* dir-item.c */ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, const char *name, diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 34f7c375567e..9cd32dc22d8a 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1127,8 +1127,10 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root, root->commit_root = btrfs_root_node(root); BUG_ON(!root->node); out: - if (location->objectid != BTRFS_TREE_LOG_OBJECTID) + if (location->objectid != BTRFS_TREE_LOG_OBJECTID) { root->ref_cows = 1; + btrfs_check_and_init_root_item(&root->root_item); + } return root; } diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 9254b3d58dbe..06cb01497a5d 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -282,6 +282,10 @@ static noinline int create_subvol(struct btrfs_root *root, inode_item->nbytes = cpu_to_le64(root->leafsize); inode_item->mode = cpu_to_le32(S_IFDIR | 0755); + root_item.flags = 0; + root_item.byte_limit = 0; + inode_item->flags = cpu_to_le64(BTRFS_INODE_ROOT_ITEM_INIT); + btrfs_set_root_bytenr(&root_item, leaf->start); btrfs_set_root_generation(&root_item, trans->transid); btrfs_set_root_level(&root_item, 0); diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 2d958be761c8..6794baf1d93f 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c @@ -473,3 +473,21 @@ again: btrfs_free_path(path); return 0; } + +/* + * Old btrfs forgets to init root_item->flags and root_item->byte_limit + * for subvolumes. To work around this problem, we steal a bit from + * root_item->inode_item->flags, and use it to indicate if those fields + * have been properly initialized. + */ +void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item) +{ + u64 inode_flags = le64_to_cpu(root_item->inode.flags); + + if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) { + inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT; + root_item->inode.flags = cpu_to_le64(inode_flags); + root_item->flags = 0; + root_item->byte_limit = 0; + } +} diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 66e4c66cc63b..7dc5b0d76a96 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -895,6 +895,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, record_root_in_trans(trans, root); btrfs_set_root_last_snapshot(&root->root_item, trans->transid); memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); + btrfs_check_and_init_root_item(new_root_item); old = btrfs_lock_root_node(root); btrfs_cow_block(trans, root, old, NULL, 0, &old); -- cgit v1.2.3 From 7f4353ff07d3fa47f2334d596d83c4465a2960ed Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Mar 2011 15:38:12 -0700 Subject: x86, mtrr, pat: Fix one cpu getting out of sync during resume commit 84ac7cdbdd0f04df6b96153f7a79127fd6e45467 upstream. On laptops with core i5/i7, there were reports that after resume graphics workloads were performing poorly on a specific AP, while the other cpu's were ok. This was observed on a 32bit kernel specifically. Debug showed that the PAT init was not happening on that AP during resume and hence it contributing to the poor workload performance on that cpu. On this system, resume flow looked like this: 1. BP starts the resume sequence and we reinit BP's MTRR's/PAT early on using mtrr_bp_restore() 2. Resume sequence brings all AP's online 3. Resume sequence now kicks off the MTRR reinit on all the AP's. 4. For some reason, between point 2 and 3, we moved from BP to one of the AP's. My guess is that printk() during resume sequence is contributing to this. We don't see similar behavior with the 64bit kernel but there is no guarantee that at this point the remaining resume sequence (after AP's bringup) has to happen on BP. 5. set_mtrr() was assuming that we are still on BP and skipped the MTRR/PAT init on that cpu (because of 1 above) 6. But we were on an AP and this led to not reprogramming PAT on this cpu leading to bad performance. Fix this by doing unconditional mtrr_if->set_all() in set_mtrr() during MTRR/PAT init. This might be unnecessary if we are still running on BP. But it is of no harm and will guarantee that after resume, all the cpu's will be in sync with respect to the MTRR/PAT registers. Signed-off-by: Suresh Siddha Signed-off-by: Andi Kleen LKML-Reference: <1301438292-28370-1-git-send-email-eric@anholt.net> Signed-off-by: Eric Anholt Tested-by: Keith Packard Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mtrr/main.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index bebabec5b448..151787e382c7 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -292,14 +292,24 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ /* * HACK! - * We use this same function to initialize the mtrrs on boot. - * The state of the boot cpu's mtrrs has been saved, and we want - * to replicate across all the APs. - * If we're doing that @reg is set to something special... + * + * We use this same function to initialize the mtrrs during boot, + * resume, runtime cpu online and on an explicit request to set a + * specific MTRR. + * + * During boot or suspend, the state of the boot cpu's mtrrs has been + * saved, and we want to replicate that across all the cpus that come + * online (either at the end of boot or resume or during a runtime cpu + * online). If we're doing that, @reg is set to something special and on + * this cpu we still do mtrr_if->set_all(). During boot/resume, this + * is unnecessary if at this point we are still on the cpu that started + * the boot/resume sequence. But there is no guarantee that we are still + * on the same cpu. So we do mtrr_if->set_all() on this cpu aswell to be + * sure that we are in sync with everyone else. */ if (reg != ~0U) mtrr_if->set(reg, base, size, type); - else if (!mtrr_aps_delayed_init) + else mtrr_if->set_all(); /* Wait for the others */ -- cgit v1.2.3 From 83d20f1306dc5ce76f195917dead2ce30351d2fb Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 25 Mar 2011 18:33:57 +0200 Subject: UBIFS: do not read flash unnecessarily commit 8b229c76765816796eec7ccd428f03bd8de8b525 upstream. This fix makes the 'dbg_check_old_index()' function return immediately if debugging is disabled, instead of executing incorrect 'goto out' which causes UBIFS to: 1. Allocate memory 2. Read the flash On every commit. OK, we do not commit that often, but it is still silly to do unneeded I/O anyway. Credits to coverity for spotting this silly issue. Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ubifs/commit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c index 37fa7ed062d8..de01f28cf44c 100644 --- a/fs/ubifs/commit.c +++ b/fs/ubifs/commit.c @@ -519,7 +519,7 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot) size_t sz; if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX)) - goto out; + return 0; INIT_LIST_HEAD(&list); -- cgit v1.2.3 From 6883e53afcda1cc1576f3bbb1e9d6dbe4012db4c Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 25 Mar 2011 19:09:54 +0200 Subject: UBIFS: fix oops on error path in read_pnode commit 54acbaaa523ca0bd284a18f67ad213c379679e86 upstream. Thanks to coverity which spotted that UBIFS will oops if 'kmalloc()' in 'read_pnode()' fails and we dereference a NULL 'pnode' pointer when we 'goto out'. Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ubifs/lpt.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c index ad7f67b827ea..ead230e08785 100644 --- a/fs/ubifs/lpt.c +++ b/fs/ubifs/lpt.c @@ -1270,10 +1270,9 @@ static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip) lnum = branch->lnum; offs = branch->offs; pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_NOFS); - if (!pnode) { - err = -ENOMEM; - goto out; - } + if (!pnode) + return -ENOMEM; + if (lnum == 0) { /* * This pnode was not written which just means that the LEB -- cgit v1.2.3 From ccc269e534996fa18bb89317a3af3451d94bb78a Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 4 Apr 2011 17:16:39 +0300 Subject: UBIFS: fix debugging failure in dbg_check_space_info commit 7da6443aca9be29c6948dcbd636ad50154d0bc0c upstream. This patch fixes a debugging failure with which looks like this: UBIFS error (pid 32313): dbg_check_space_info: free space changed from 6019344 to 6022654 The reason for this failure is described in the comment this patch adds to the code. But in short - 'c->freeable_cnt' may be different before and after re-mounting, and this is normal. So the debugging code should make sure that free space calculations do not depend on 'c->freeable_cnt'. A similar issue has been reported here: http://lists.infradead.org/pipermail/linux-mtd/2011-April/034647.html This patch should fix it. For the -stable guys: this patch is only relevant for kernels 2.6.30 onwards. Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ubifs/debug.c | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index c2a68baa782f..923d697a302a 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -961,11 +961,39 @@ void dbg_dump_index(struct ubifs_info *c) void dbg_save_space_info(struct ubifs_info *c) { struct ubifs_debug_info *d = c->dbg; - - ubifs_get_lp_stats(c, &d->saved_lst); + int freeable_cnt; spin_lock(&c->space_lock); + memcpy(&d->saved_lst, &c->lst, sizeof(struct ubifs_lp_stats)); + + /* + * We use a dirty hack here and zero out @c->freeable_cnt, because it + * affects the free space calculations, and UBIFS might not know about + * all freeable eraseblocks. Indeed, we know about freeable eraseblocks + * only when we read their lprops, and we do this only lazily, upon the + * need. So at any given point of time @c->freeable_cnt might be not + * exactly accurate. + * + * Just one example about the issue we hit when we did not zero + * @c->freeable_cnt. + * 1. The file-system is mounted R/O, c->freeable_cnt is %0. We save the + * amount of free space in @d->saved_free + * 2. We re-mount R/W, which makes UBIFS to read the "lsave" + * information from flash, where we cache LEBs from various + * categories ('ubifs_remount_fs()' -> 'ubifs_lpt_init()' + * -> 'lpt_init_wr()' -> 'read_lsave()' -> 'ubifs_lpt_lookup()' + * -> 'ubifs_get_pnode()' -> 'update_cats()' + * -> 'ubifs_add_to_cat()'). + * 3. Lsave contains a freeable eraseblock, and @c->freeable_cnt + * becomes %1. + * 4. We calculate the amount of free space when the re-mount is + * finished in 'dbg_check_space_info()' and it does not match + * @d->saved_free. + */ + freeable_cnt = c->freeable_cnt; + c->freeable_cnt = 0; d->saved_free = ubifs_get_free_space_nolock(c); + c->freeable_cnt = freeable_cnt; spin_unlock(&c->space_lock); } @@ -982,12 +1010,15 @@ int dbg_check_space_info(struct ubifs_info *c) { struct ubifs_debug_info *d = c->dbg; struct ubifs_lp_stats lst; - long long avail, free; + long long free; + int freeable_cnt; spin_lock(&c->space_lock); - avail = ubifs_calc_available(c, c->min_idx_lebs); + freeable_cnt = c->freeable_cnt; + c->freeable_cnt = 0; + free = ubifs_get_free_space_nolock(c); + c->freeable_cnt = freeable_cnt; spin_unlock(&c->space_lock); - free = ubifs_get_free_space(c); if (free != d->saved_free) { ubifs_err("free space changed from %lld to %lld", -- cgit v1.2.3 From b229ff76e622cb4ba1e79c21764ff20b8c7f8fbe Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 31 Mar 2011 18:36:52 +0200 Subject: quota: Don't write quota info in dquot_commit() commit b03f24567ce7caf2420b8be4c6eb74c191d59a91 upstream. There's no reason to write quota info in dquot_commit(). The writing is a relict from the old days when we didn't have dquot_acquire() and dquot_release() and thus dquot_commit() could have created / removed quota structures from the file. These days dquot_commit() only updates usage counters / limits in quota structure and thus there's no need to write quota info. This also fixes an issue with journaling filesystem which didn't reserve enough space in the transaction for write of quota info (it could have been dirty at the time of dquot_commit() because of a race with other operation changing it). Reported-and-tested-by: Lukas Czerner Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/quota/dquot.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 437d2ca2de97..42b08818d0e2 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -422,7 +422,7 @@ EXPORT_SYMBOL(dquot_acquire); */ int dquot_commit(struct dquot *dquot) { - int ret = 0, ret2 = 0; + int ret = 0; struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); mutex_lock(&dqopt->dqio_mutex); @@ -434,15 +434,10 @@ int dquot_commit(struct dquot *dquot) spin_unlock(&dq_list_lock); /* Inactive dquot can be only if there was error during read/init * => we have better not writing it */ - if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) { + if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot); - if (info_dirty(&dqopt->info[dquot->dq_type])) { - ret2 = dqopt->ops[dquot->dq_type]->write_file_info( - dquot->dq_sb, dquot->dq_type); - } - if (ret >= 0) - ret = ret2; - } + else + ret = -EIO; out_sem: mutex_unlock(&dqopt->dqio_mutex); return ret; -- cgit v1.2.3 From a912dbb16e083224bab946591e2251278a1dd358 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 7 Apr 2011 07:35:50 -0700 Subject: mm: avoid wrapping vm_pgoff in mremap() commit 982134ba62618c2d69fbbbd166d0a11ee3b7e3d8 upstream. The normal mmap paths all avoid creating a mapping where the pgoff inside the mapping could wrap around due to overflow. However, an expanding mremap() can take such a non-wrapping mapping and make it bigger and cause a wrapping condition. Noticed by Robert Swiecki when running a system call fuzzer, where it caused a BUG_ON() due to terminally confusing the vma_prio_tree code. A vma dumping patch by Hugh then pinpointed the crazy wrapped case. Reported-and-tested-by: Robert Swiecki Acked-by: Hugh Dickins Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- mm/mremap.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/mm/mremap.c b/mm/mremap.c index 10d5f6264514..97de5aef9431 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -274,9 +274,16 @@ static struct vm_area_struct *vma_to_resize(unsigned long addr, if (old_len > vma->vm_end - addr) goto Efault; - if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) { - if (new_len > old_len) + /* Need to be careful about a growing mapping */ + if (new_len > old_len) { + unsigned long pgoff; + + if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) goto Efault; + pgoff = (addr - vma->vm_start) >> PAGE_SHIFT; + pgoff += vma->vm_pgoff; + if (pgoff + (new_len >> PAGE_SHIFT) < pgoff) + goto Einval; } if (vma->vm_flags & VM_LOCKED) { -- cgit v1.2.3 From 50ff23dee524be20ac74a545df4ccad9dbf94c14 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 2 Apr 2011 11:31:29 +0200 Subject: p54usb: IDs for two new devices commit 220107610c7c2c9703e09eb363e8ab31025b9315 upstream. Reported-by: Mark Davis [via p54/devices wiki] Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/p54/p54usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 2943f04e109e..e3924a99f44b 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -56,6 +56,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */ {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */ {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */ + {USB_DEVICE(0x0bf8, 0x1007)}, /* Fujitsu E-5400 USB */ {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */ {USB_DEVICE(0x0db0, 0x6826)}, /* MSI UB54G (MS-6826) */ {USB_DEVICE(0x107b, 0x55f2)}, /* Gateway WGU-210 (Gemtek) */ @@ -68,6 +69,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */ {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */ {USB_DEVICE(0x2001, 0x3703)}, /* DLink DWL-G122 */ + {USB_DEVICE(0x2001, 0x3762)}, /* Conceptronic C54U */ {USB_DEVICE(0x5041, 0x2234)}, /* Linksys WUSB54G */ {USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */ -- cgit v1.2.3 From 4c4b0c5672df6404af076f47f9625e4eaa30954c Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 30 Mar 2011 14:02:46 -0400 Subject: b43: allocate receive buffers big enough for max frame len + offset commit c85ce65ecac078ab1a1835c87c4a6319cf74660a upstream. Otherwise, skb_put inside of dma_rx can fail... https://bugzilla.kernel.org/show_bug.cgi?id=32042 Signed-off-by: John W. Linville Acked-by: Larry Finger Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/b43/dma.c | 2 +- drivers/net/wireless/b43/dma.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index fa40fdfea719..b8900f09588f 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1538,7 +1538,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) dmaaddr = meta->dmaaddr; goto drop_recycle_buffer; } - if (unlikely(len > ring->rx_buffersize)) { + if (unlikely(len + ring->frameoffset > ring->rx_buffersize)) { /* The data did not fit into one descriptor buffer * and is split over multiple buffers. * This should never happen, as we try to allocate buffers diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index dc91944d6022..a9282d73b066 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -163,7 +163,7 @@ struct b43_dmadesc_generic { /* DMA engine tuning knobs */ #define B43_TXRING_SLOTS 256 #define B43_RXRING_SLOTS 64 -#define B43_DMA0_RX_BUFFERSIZE IEEE80211_MAX_FRAME_LEN +#define B43_DMA0_RX_BUFFERSIZE (B43_DMA0_RX_FRAMEOFFSET + IEEE80211_MAX_FRAME_LEN) /* Pointer poison */ #define B43_DMA_PTR_POISON ((void *)ERR_PTR(-ENOMEM)) -- cgit v1.2.3 From de204eb252ffd7786bcdead3a88d04e17b98a993 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Mon, 14 Feb 2011 13:54:26 +0300 Subject: Bluetooth: sco: fix information leak to userspace commit c4c896e1471aec3b004a693c689f60be3b17ac86 upstream. struct sco_conninfo has one padding byte in the end. Local variable cinfo of type sco_conninfo is copied to userspace with this uninizialized one byte, leading to old stack contents leak. Signed-off-by: Vasiliy Kulikov Signed-off-by: Gustavo F. Padovan Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/bluetooth/sco.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index d0927d1fdada..f3f8d4cd55b5 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -700,6 +700,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname, char __user break; } + memset(&cinfo, 0, sizeof(cinfo)); cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle; memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3); -- cgit v1.2.3 From ce0f98ea90a8171cdaf249c0c623b455931d69ec Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Mon, 14 Feb 2011 16:49:23 +0100 Subject: bridge: netfilter: fix information leak commit d846f71195d57b0bbb143382647c2c6638b04c5a upstream. Struct tmp is copied from userspace. It is not checked whether the "name" field is NULL terminated. This may lead to buffer overflow and passing contents of kernel stack as a module name to try_then_request_module() and, consequently, to modprobe commandline. It would be seen by all userspace processes. Signed-off-by: Vasiliy Kulikov Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/bridge/netfilter/ebtables.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 59ca00e40dec..62675dc51179 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -1098,6 +1098,8 @@ static int do_replace(struct net *net, const void __user *user, if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter)) return -ENOMEM; + tmp.name[sizeof(tmp.name) - 1] = 0; + countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids; newinfo = vmalloc(sizeof(*newinfo) + countersize); if (!newinfo) -- cgit v1.2.3 From 794cf4569083bd3a54bcba5068e2beaea5663f2d Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Mon, 14 Feb 2011 13:54:31 +0300 Subject: Bluetooth: bnep: fix buffer overflow commit 43629f8f5ea32a998d06d1bb41eefa0e821ff573 upstream. Struct ca is copied from userspace. It is not checked whether the "device" field is NULL terminated. This potentially leads to BUG() inside of alloc_netdev_mqs() and/or information leak by creating a device with a name made of contents of kernel stack. Signed-off-by: Vasiliy Kulikov Signed-off-by: Gustavo F. Padovan Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/bluetooth/bnep/sock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 2862f53b66b1..d935da71ab3b 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c @@ -88,6 +88,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long sockfd_put(nsock); return -EBADFD; } + ca.device[sizeof(ca.device)-1] = 0; err = bnep_add_connection(&ca, nsock); if (!err) { -- cgit v1.2.3 From 40e16b189b9594052a8efb92c4c0f0249dd4479b Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Thu, 24 Mar 2011 14:51:21 -0300 Subject: Bluetooth: add support for Apple MacBook Pro 8,2 commit 63a8588debd4dc72becb9e27add9343c76301c7d upstream. Just adding the vendor details makes it work fine. Signed-off-by: Marc-Antoine Perennou Signed-off-by: Gustavo F. Padovan Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 6fcb97124be8..c9e2dc830b22 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -62,6 +62,9 @@ static struct usb_device_id btusb_table[] = { /* Apple iMac11,1 */ { USB_DEVICE(0x05ac, 0x8215) }, + /* Apple MacBookPro8,2 */ + { USB_DEVICE(0x05ac, 0x821a) }, + /* AVM BlueFRITZ! USB v2.0 */ { USB_DEVICE(0x057c, 0x3800) }, -- cgit v1.2.3 From 3778903dd4568b9f5f8a8cd0ea3c09b40307ecd0 Mon Sep 17 00:00:00 2001 From: Goldwyn Rodrigues Date: Thu, 17 Feb 2011 09:44:40 -0600 Subject: Treat writes as new when holes span across page boundaries commit 272b62c1f0f6f742046e45b50b6fec98860208a0 upstream. When a hole spans across page boundaries, the next write forces a read of the block. This could end up reading existing garbage data from the disk in ocfs2_map_page_blocks. This leads to non-zero holes. In order to avoid this, mark the writes as new when the holes span across page boundaries. Signed-off-by: Goldwyn Rodrigues Signed-off-by: jlbec Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ocfs2/aops.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 96337a4fbbdf..1514e271d1b9 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -1039,6 +1039,12 @@ static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno, ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), cpos, &cluster_start, &cluster_end); + /* treat the write as new if the a hole/lseek spanned across + * the page boundary. + */ + new = new | ((i_size_read(inode) <= page_offset(page)) && + (page_offset(page) <= user_pos)); + if (page == wc->w_target_page) { map_from = user_pos & (PAGE_CACHE_SIZE - 1); map_to = map_from + user_len; -- cgit v1.2.3 From 8f6e8f4068274710a9d6aaad0089a13494daf753 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Tue, 29 Mar 2011 13:31:25 +0200 Subject: char/tpm: Fix unitialized usage of data buffer commit 1309d7afbed112f0e8e90be9af975550caa0076b upstream. This patch fixes information leakage to the userspace by initializing the data buffer to zero. Reported-by: Peter Huewe Signed-off-by: Peter Huewe Signed-off-by: Marcel Selhorst Signed-off-by: Andi Kleen [ Also removed the silly "* sizeof(u8)". If that isn't 1, we have way deeper problems than a simple multiplication can fix. - Linus ] Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 2ec5f33cdbd0..12c089863e59 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -970,7 +970,7 @@ int tpm_open(struct inode *inode, struct file *file) return -EBUSY; } - chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); + chip->data_buffer = kzalloc(TPM_BUFSIZE, GFP_KERNEL); if (chip->data_buffer == NULL) { clear_bit(0, &chip->is_open); put_device(chip->dev); -- cgit v1.2.3 From 754e601978068dab6d6ed3f25fd3fbb7ec9d28c2 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Tue, 15 Mar 2011 13:36:05 +0100 Subject: netfilter: ip_tables: fix infoleak to userspace commit 78b79876761b86653df89c48a7010b5cbd41a84a upstream. Structures ipt_replace, compat_ipt_replace, and xt_get_revision are copied from userspace. Fields of these structs that are zero-terminated strings are not checked. When they are used as argument to a format string containing "%s" in request_module(), some sensitive information is leaked to userspace via argument of spawned modprobe process. The first and the third bugs were introduced before the git epoch; the second was introduced in 2722971c (v2.6.17-rc1). To trigger the bug one should have CAP_NET_ADMIN. Signed-off-by: Vasiliy Kulikov Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ipv4/netfilter/ip_tables.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 402ce75432e4..e8c4ddf055b0 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1273,6 +1273,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len) /* overflow check */ if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) return -ENOMEM; + tmp.name[sizeof(tmp.name)-1] = 0; newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) @@ -1817,6 +1818,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) return -ENOMEM; if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) return -ENOMEM; + tmp.name[sizeof(tmp.name)-1] = 0; newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) @@ -2046,6 +2048,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) ret = -EFAULT; break; } + rev.name[sizeof(rev.name)-1] = 0; if (cmd == IPT_SO_GET_REVISION_TARGET) target = 1; -- cgit v1.2.3 From d52f8b882ab7a4c44dc04b7195266c75e236b4f0 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Tue, 15 Mar 2011 13:35:21 +0100 Subject: netfilter: arp_tables: fix infoleak to userspace commit 42eab94fff18cb1091d3501cd284d6bd6cc9c143 upstream. Structures ipt_replace, compat_ipt_replace, and xt_get_revision are copied from userspace. Fields of these structs that are zero-terminated strings are not checked. When they are used as argument to a format string containing "%s" in request_module(), some sensitive information is leaked to userspace via argument of spawned modprobe process. The first bug was introduced before the git epoch; the second is introduced by 6b7d31fc (v2.6.15-rc1); the third is introduced by 6b7d31fc (v2.6.15-rc1). To trigger the bug one should have CAP_NET_ADMIN. Signed-off-by: Vasiliy Kulikov Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ipv4/netfilter/arp_tables.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index aaab5aafcee8..956584d8f7f4 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -1081,6 +1081,7 @@ static int do_replace(struct net *net, const void __user *user, /* overflow check */ if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) return -ENOMEM; + tmp.name[sizeof(tmp.name)-1] = 0; newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) @@ -1502,6 +1503,7 @@ static int compat_do_replace(struct net *net, void __user *user, return -ENOMEM; if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) return -ENOMEM; + tmp.name[sizeof(tmp.name)-1] = 0; newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) @@ -1754,6 +1756,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len ret = -EFAULT; break; } + rev.name[sizeof(rev.name)-1] = 0; try_then_request_module(xt_find_revision(NFPROTO_ARP, rev.name, rev.revision, 1, &ret), -- cgit v1.2.3 From 9c09bd6e205093f8344028671260efd1687f26b9 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Sun, 20 Mar 2011 15:42:52 +0100 Subject: netfilter: ipt_CLUSTERIP: fix buffer overflow commit 961ed183a9fd080cf306c659b8736007e44065a5 upstream. 'buffer' string is copied from userspace. It is not checked whether it is zero terminated. This may lead to overflow inside of simple_strtoul(). Changli Gao suggested to copy not more than user supplied 'size' bytes. It was introduced before the git epoch. Files "ipt_CLUSTERIP/*" are root writable only by default, however, on some setups permissions might be relaxed to e.g. network admin user. Signed-off-by: Vasiliy Kulikov Acked-by: Changli Gao Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ipv4/netfilter/ipt_CLUSTERIP.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index f91c94b9a790..de773016cbea 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -663,8 +663,11 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input, char buffer[PROC_WRITELEN+1]; unsigned long nodenum; - if (copy_from_user(buffer, input, PROC_WRITELEN)) + if (size > PROC_WRITELEN) + return -EIO; + if (copy_from_user(buffer, input, size)) return -EFAULT; + buffer[size] = 0; if (*buffer == '+') { nodenum = simple_strtoul(buffer+1, NULL, 10); -- cgit v1.2.3 From 29701eac578602bcb6a1a034b964cb75656c6939 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Tue, 15 Mar 2011 13:37:13 +0100 Subject: ipv6: netfilter: ip6_tables: fix infoleak to userspace commit 6a8ab060779779de8aea92ce3337ca348f973f54 upstream. Structures ip6t_replace, compat_ip6t_replace, and xt_get_revision are copied from userspace. Fields of these structs that are zero-terminated strings are not checked. When they are used as argument to a format string containing "%s" in request_module(), some sensitive information is leaked to userspace via argument of spawned modprobe process. The first bug was introduced before the git epoch; the second was introduced in 3bc3fe5e (v2.6.25-rc1); the third is introduced by 6b7d31fc (v2.6.15-rc1). To trigger the bug one should have CAP_NET_ADMIN. Signed-off-by: Vasiliy Kulikov Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ipv6/netfilter/ip6_tables.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 211229887e2c..008e1861ad2d 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1289,6 +1289,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len) /* overflow check */ if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) return -ENOMEM; + tmp.name[sizeof(tmp.name)-1] = 0; newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) @@ -1835,6 +1836,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) return -ENOMEM; if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) return -ENOMEM; + tmp.name[sizeof(tmp.name)-1] = 0; newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) @@ -2064,6 +2066,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) ret = -EFAULT; break; } + rev.name[sizeof(rev.name)-1] = 0; if (cmd == IP6T_SO_GET_REVISION_TARGET) target = 1; -- cgit v1.2.3 From 4749480caa4baa97804bbce1ccf873d29b04ca43 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Fri, 4 Feb 2011 15:23:36 +0300 Subject: mfd: ab3100: world-writable debugfs *_priv files commit f8a0697722d12a201588225999cfc8bfcbc82781 upstream. Don't allow everybody to change device hardware registers. Signed-off-by: Vasiliy Kulikov Acked-by: Linus Walleij Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/mfd/ab3100-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 66379b413906..c55e0a3aaba4 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -611,7 +611,7 @@ static void ab3100_setup_debugfs(struct ab3100 *ab3100) ab3100_get_priv.ab3100 = ab3100; ab3100_get_priv.mode = false; ab3100_get_reg_file = debugfs_create_file("get_reg", - S_IWUGO, ab3100_dir, &ab3100_get_priv, + S_IWUSR, ab3100_dir, &ab3100_get_priv, &ab3100_get_set_reg_fops); if (!ab3100_get_reg_file) { err = -ENOMEM; @@ -621,7 +621,7 @@ static void ab3100_setup_debugfs(struct ab3100 *ab3100) ab3100_set_priv.ab3100 = ab3100; ab3100_set_priv.mode = true; ab3100_set_reg_file = debugfs_create_file("set_reg", - S_IWUGO, ab3100_dir, &ab3100_set_priv, + S_IWUSR, ab3100_dir, &ab3100_set_priv, &ab3100_get_set_reg_fops); if (!ab3100_set_reg_file) { err = -ENOMEM; -- cgit v1.2.3 From faf71f45b0485c3d97ed987489185288ba94b638 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Tue, 22 Mar 2011 16:34:53 -0700 Subject: drivers/rtc/rtc-ds1511.c: world-writable sysfs nvram file commit 49d50fb1c28738ef6bad0c2b87d5355a1653fed5 upstream. Don't allow everybogy to write to NVRAM. Signed-off-by: Vasiliy Kulikov Signed-off-by: Andi Kleen Cc: Andy Sharp Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-ds1511.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 37268e97de49..afeb5469708b 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -485,7 +485,7 @@ ds1511_nvram_write(struct file *filp, struct kobject *kobj, static struct bin_attribute ds1511_nvram_attr = { .attr = { .name = "nvram", - .mode = S_IRUGO | S_IWUGO, + .mode = S_IRUGO | S_IWUSR, }, .size = DS1511_RAM_MAX, .read = ds1511_nvram_read, -- cgit v1.2.3 From 8bc9047b8496f04f9a8239e7ff2452c6b5668253 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Tue, 22 Mar 2011 16:34:01 -0700 Subject: drivers/misc/ep93xx_pwm.c: world-writable sysfs files commit deb187e72470b0382d4f0cb859e76e1ebc3a1082 upstream. Don't allow everybody to change device settings. Signed-off-by: Vasiliy Kulikov Acked-by: Hartley Sweeten Signed-off-by: Andi Kleen Cc: Matthieu Crapet Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ep93xx_pwm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index 46b3439673e9..16d7179e2f9b 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c @@ -249,11 +249,11 @@ static ssize_t ep93xx_pwm_set_invert(struct device *dev, static DEVICE_ATTR(min_freq, S_IRUGO, ep93xx_pwm_get_min_freq, NULL); static DEVICE_ATTR(max_freq, S_IRUGO, ep93xx_pwm_get_max_freq, NULL); -static DEVICE_ATTR(freq, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(freq, S_IWUSR | S_IRUGO, ep93xx_pwm_get_freq, ep93xx_pwm_set_freq); -static DEVICE_ATTR(duty_percent, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(duty_percent, S_IWUSR | S_IRUGO, ep93xx_pwm_get_duty_percent, ep93xx_pwm_set_duty_percent); -static DEVICE_ATTR(invert, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(invert, S_IWUSR | S_IRUGO, ep93xx_pwm_get_invert, ep93xx_pwm_set_invert); static struct attribute *ep93xx_pwm_attrs[] = { -- cgit v1.2.3 From dc29b760f88ce16053425113e49f1eba4f75422d Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Thu, 17 Mar 2011 01:40:10 +0000 Subject: econet: 4 byte infoleak to the network commit 67c5c6cb8129c595f21e88254a3fc6b3b841ae8e upstream. struct aunhdr has 4 padding bytes between 'pad' and 'handle' fields on x86_64. These bytes are not initialized in the variable 'ah' before sending 'ah' to the network. This leads to 4 bytes kernel stack infoleak. This bug was introduced before the git epoch. Signed-off-by: Vasiliy Kulikov Acked-by: Phil Blundell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/econet/af_econet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index c8d356c0f815..ef3593f3cea3 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -435,10 +435,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, udpdest.sin_addr.s_addr = htonl(network | addr.station); } + memset(&ah, 0, sizeof(ah)); ah.port = port; ah.cb = cb & 0x7f; ah.code = 2; /* magic */ - ah.pad = 0; /* tack our header on the front of the iovec */ size = sizeof(struct aunhdr); -- cgit v1.2.3 From 95e07fd5a69dd641592cba4f225e898c441dca6b Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 23 Mar 2011 10:53:41 -0400 Subject: sound/oss: remove offset from load_patch callbacks commit b769f49463711205d57286e64cf535ed4daf59e9 upstream. Was: [PATCH] sound/oss/midi_synth: prevent underflow, use of uninitialized value, and signedness issue The offset passed to midi_synth_load_patch() can be essentially arbitrary. If it's greater than the header length, this will result in a copy_from_user(dst, src, negative_val). While this will just return -EFAULT on x86, on other architectures this may cause memory corruption. Additionally, the length field of the sysex_info structure may not be initialized prior to its use. Finally, a signed comparison may result in an unintentionally large loop. On suggestion by Takashi Iwai, version two removes the offset argument from the load_patch callbacks entirely, which also resolves similar issues in opl3. Compile tested only. v3 adjusts comments and hopefully gets copy offsets right. Signed-off-by: Dan Rosenberg Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/oss/dev_table.h | 2 +- sound/oss/midi_synth.c | 30 +++++++++++++----------------- sound/oss/midi_synth.h | 2 +- sound/oss/opl3.c | 8 ++------ sound/oss/sequencer.c | 2 +- 5 files changed, 18 insertions(+), 26 deletions(-) diff --git a/sound/oss/dev_table.h b/sound/oss/dev_table.h index b7617bee6388..0199a317c5a9 100644 --- a/sound/oss/dev_table.h +++ b/sound/oss/dev_table.h @@ -271,7 +271,7 @@ struct synth_operations void (*reset) (int dev); void (*hw_control) (int dev, unsigned char *event); int (*load_patch) (int dev, int format, const char __user *addr, - int offs, int count, int pmgr_flag); + int count, int pmgr_flag); void (*aftertouch) (int dev, int voice, int pressure); void (*controller) (int dev, int voice, int ctrl_num, int value); void (*panning) (int dev, int voice, int value); diff --git a/sound/oss/midi_synth.c b/sound/oss/midi_synth.c index 3bc7104c5379..11685f12569d 100644 --- a/sound/oss/midi_synth.c +++ b/sound/oss/midi_synth.c @@ -476,7 +476,7 @@ EXPORT_SYMBOL(midi_synth_hw_control); int midi_synth_load_patch(int dev, int format, const char __user *addr, - int offs, int count, int pmgr_flag) + int count, int pmgr_flag) { int orig_dev = synth_devs[dev]->midi_dev; @@ -491,33 +491,29 @@ midi_synth_load_patch(int dev, int format, const char __user *addr, if (!prefix_cmd(orig_dev, 0xf0)) return 0; + /* Invalid patch format */ if (format != SYSEX_PATCH) - { -/* printk("MIDI Error: Invalid patch format (key) 0x%x\n", format);*/ return -EINVAL; - } + + /* Patch header too short */ if (count < hdr_size) - { -/* printk("MIDI Error: Patch header too short\n");*/ return -EINVAL; - } + count -= hdr_size; /* - * Copy the header from user space but ignore the first bytes which have - * been transferred already. + * Copy the header from user space */ - if(copy_from_user(&((char *) &sysex)[offs], &(addr)[offs], hdr_size - offs)) + if (copy_from_user(&sysex, addr, hdr_size)) return -EFAULT; - - if (count < sysex.len) - { -/* printk(KERN_WARNING "MIDI Warning: Sysex record too short (%d<%d)\n", count, (int) sysex.len);*/ + + /* Sysex record too short */ + if ((unsigned)count < (unsigned)sysex.len) sysex.len = count; - } - left = sysex.len; - src_offs = 0; + + left = sysex.len; + src_offs = 0; for (i = 0; i < left && !signal_pending(current); i++) { diff --git a/sound/oss/midi_synth.h b/sound/oss/midi_synth.h index 6bc9d00bc77c..b64ddd6c4abc 100644 --- a/sound/oss/midi_synth.h +++ b/sound/oss/midi_synth.h @@ -8,7 +8,7 @@ int midi_synth_open (int dev, int mode); void midi_synth_close (int dev); void midi_synth_hw_control (int dev, unsigned char *event); int midi_synth_load_patch (int dev, int format, const char __user * addr, - int offs, int count, int pmgr_flag); + int count, int pmgr_flag); void midi_synth_panning (int dev, int channel, int pressure); void midi_synth_aftertouch (int dev, int channel, int pressure); void midi_synth_controller (int dev, int channel, int ctrl_num, int value); diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c index f4ffdff9b245..407cd677950b 100644 --- a/sound/oss/opl3.c +++ b/sound/oss/opl3.c @@ -820,7 +820,7 @@ static void opl3_hw_control(int dev, unsigned char *event) } static int opl3_load_patch(int dev, int format, const char __user *addr, - int offs, int count, int pmgr_flag) + int count, int pmgr_flag) { struct sbi_instrument ins; @@ -830,11 +830,7 @@ static int opl3_load_patch(int dev, int format, const char __user *addr, return -EINVAL; } - /* - * What the fuck is going on here? We leave junk in the beginning - * of ins and then check the field pretty close to that beginning? - */ - if(copy_from_user(&((char *) &ins)[offs], addr + offs, sizeof(ins) - offs)) + if (copy_from_user(&ins, addr, sizeof(ins))) return -EFAULT; if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR) diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c index e85789e53816..a0072a9b03dc 100644 --- a/sound/oss/sequencer.c +++ b/sound/oss/sequencer.c @@ -241,7 +241,7 @@ int sequencer_write(int dev, struct file *file, const char __user *buf, int coun return -ENXIO; fmt = (*(short *) &event_rec[0]) & 0xffff; - err = synth_devs[dev]->load_patch(dev, fmt, buf, p + 4, c, 0); + err = synth_devs[dev]->load_patch(dev, fmt, buf + p, c, 0); if (err < 0) return err; -- cgit v1.2.3 From 38a4189d5c25a817018416dee94b52bd9be2e7c5 Mon Sep 17 00:00:00 2001 From: Kulikov Vasiliy Date: Wed, 28 Jul 2010 20:41:17 +0400 Subject: sound: oss: midi_synth: check get_user() return value commit b3390ceab95601afc12213c3ec5551d3bc7b638f upstream. get_user() may fail, if so return -EFAULT. Signed-off-by: Kulikov Vasiliy Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/oss/midi_synth.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/oss/midi_synth.c b/sound/oss/midi_synth.c index 11685f12569d..2292c230d7e6 100644 --- a/sound/oss/midi_synth.c +++ b/sound/oss/midi_synth.c @@ -519,7 +519,9 @@ midi_synth_load_patch(int dev, int format, const char __user *addr, { unsigned char data; - get_user(*(unsigned char *) &data, (unsigned char __user *) &((addr)[hdr_size + i])); + if (get_user(data, + (unsigned char __user *)(addr + hdr_size + i))) + return -EFAULT; eox_seen = (i > 0 && data & 0x80); /* End of sysex */ -- cgit v1.2.3 From 760a5d738e7fe9bcdf6dd6a573541edb01a95ac2 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 29 Jan 2011 20:44:54 -0800 Subject: gro: Reset dev pointer on reuse commit 66c46d741e2e60f0e8b625b80edb0ab820c46d7a upstream. On older kernels the VLAN code may zero skb->dev before dropping it and causing it to be reused by GRO. Unfortunately we didn't reset skb->dev in that case which causes the next GRO user to get a bogus skb->dev pointer. This particular problem no longer happens with the current upstream kernel due to changes in VLAN processing. However, for correctness we should still reset the skb->dev pointer in the GRO reuse function in case a future user does the same thing. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller Signed-off-by: Brandon Philips Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/core/dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/dev.c b/net/core/dev.c index 7c3e7c36c0b7..bd6c169e2506 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3231,6 +3231,7 @@ void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) { __skb_pull(skb, skb_headlen(skb)); skb_reserve(skb, NET_IP_ALIGN - skb_headroom(skb)); + skb->dev = napi->dev; napi->skb = skb; } -- cgit v1.2.3 From e0908c530987e7df4cfb4ef7d94cd2c0e17f6b95 Mon Sep 17 00:00:00 2001 From: Andy Gospodarek Date: Wed, 2 Feb 2011 14:53:25 -0800 Subject: gro: reset skb_iif on reuse commit 6d152e23ad1a7a5b40fef1f42e017d66e6115159 upstream. Like Herbert's change from a few days ago: 66c46d741e2e60f0e8b625b80edb0ab820c46d7a gro: Reset dev pointer on reuse this may not be necessary at this point, but we should still clean up the skb->skb_iif. If not we may end up with an invalid valid for skb->skb_iif when the skb is reused and the check is done in __netif_receive_skb. Signed-off-by: Andy Gospodarek Signed-off-by: David S. Miller Signed-off-by: Brandon Philips Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/core/dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/dev.c b/net/core/dev.c index bd6c169e2506..85e3f8dc243c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3232,6 +3232,7 @@ void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) __skb_pull(skb, skb_headlen(skb)); skb_reserve(skb, NET_IP_ALIGN - skb_headroom(skb)); skb->dev = napi->dev; + skb->skb_iif = 0; napi->skb = skb; } -- cgit v1.2.3 From 297a19bdbec76bbf4668abd4a8eb4bcf6b4019f8 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 29 Mar 2011 21:29:54 +0200 Subject: x86, microcode, AMD: Extend ucode size verification Upstream commit: 44d60c0f5c58c2168f31df9a481761451840eb54 The different families have a different max size for the ucode patch, adjust size checking to the family we're running on. Also, do not vzalloc the max size of the ucode but only the actual size that is passed on from the firmware loader. Cc: Signed-off-by: Borislav Petkov Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/kernel/microcode_amd.c | 65 ++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index e1af7c055c7d..67381a227d67 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -66,7 +66,6 @@ struct microcode_amd { unsigned int mpb[0]; }; -#define UCODE_MAX_SIZE 2048 #define UCODE_CONTAINER_SECTION_HDR 8 #define UCODE_CONTAINER_HEADER_SIZE 12 @@ -125,6 +124,37 @@ static int get_matching_microcode(int cpu, void *mc, int rev) return 1; } +static unsigned int verify_ucode_size(int cpu, const u8 *buf, unsigned int size) +{ + struct cpuinfo_x86 *c = &cpu_data(cpu); + unsigned int max_size, actual_size; + +#define F1XH_MPB_MAX_SIZE 2048 +#define F14H_MPB_MAX_SIZE 1824 +#define F15H_MPB_MAX_SIZE 4096 + + switch (c->x86) { + case 0x14: + max_size = F14H_MPB_MAX_SIZE; + break; + case 0x15: + max_size = F15H_MPB_MAX_SIZE; + break; + default: + max_size = F1XH_MPB_MAX_SIZE; + break; + } + + actual_size = buf[4] + (buf[5] << 8); + + if (actual_size > size || actual_size > max_size) { + pr_err("section size mismatch\n"); + return 0; + } + + return actual_size; +} + static int apply_microcode_amd(int cpu) { u32 rev, dummy; @@ -162,11 +192,11 @@ static int get_ucode_data(void *to, const u8 *from, size_t n) } static void * -get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size) +get_next_ucode(int cpu, const u8 *buf, unsigned int size, unsigned int *mc_size) { - unsigned int total_size; + unsigned int actual_size = 0; u8 section_hdr[UCODE_CONTAINER_SECTION_HDR]; - void *mc; + void *mc = NULL; if (get_ucode_data(section_hdr, buf, UCODE_CONTAINER_SECTION_HDR)) return NULL; @@ -176,23 +206,18 @@ get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size) return NULL; } - total_size = (unsigned long) (section_hdr[4] + (section_hdr[5] << 8)); - - if (total_size > size || total_size > UCODE_MAX_SIZE) { - pr_err("error: size mismatch\n"); + actual_size = verify_ucode_size(cpu, buf, size); + if (!actual_size) return NULL; - } - mc = vmalloc(UCODE_MAX_SIZE); - if (mc) { - memset(mc, 0, UCODE_MAX_SIZE); - if (get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, - total_size)) { - vfree(mc); - mc = NULL; - } else - *mc_size = total_size + UCODE_CONTAINER_SECTION_HDR; - } + mc = vmalloc(actual_size); + if (!mc) + return NULL; + + memset(mc, 0, actual_size); + get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, actual_size); + *mc_size = actual_size + UCODE_CONTAINER_SECTION_HDR; + return mc; } @@ -258,7 +283,7 @@ generic_load_microcode(int cpu, const u8 *data, size_t size) unsigned int uninitialized_var(mc_size); struct microcode_header_amd *mc_header; - mc = get_next_ucode(ucode_ptr, leftover, &mc_size); + mc = get_next_ucode(cpu, ucode_ptr, leftover, &mc_size); if (!mc) break; -- cgit v1.2.3 From f5228c7c5062d5257f881d2f9c6a355215ce79b2 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Tue, 15 Mar 2011 22:09:55 +0000 Subject: Squashfs: handle corruption of directory structure commit 44cff8a9ee8a974f9e931df910688e7fc1f0b0f9 upstream. Handle the rare case where a directory metadata block is uncompressed and corrupted, leading to a kernel oops in directory scanning (memcpy). Normally corruption is detected at the decompression stage and dealt with then, however, this will not happen if: - metadata isn't compressed (users can optionally request no metadata compression), or - the compressed metadata block was larger than the original, in which case the uncompressed version was used, or - the data was corrupt after decompression This patch fixes this by adding some sanity checks against known maximum values. Signed-off-by: Phillip Lougher Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/squashfs/dir.c | 9 +++++++++ fs/squashfs/namei.c | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/fs/squashfs/dir.c b/fs/squashfs/dir.c index 12b933ac6585..a37d445cfff9 100644 --- a/fs/squashfs/dir.c +++ b/fs/squashfs/dir.c @@ -172,6 +172,11 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) length += sizeof(dirh); dir_count = le32_to_cpu(dirh.count) + 1; + + /* dir_count should never be larger than 256 */ + if (dir_count > 256) + goto failed_read; + while (dir_count--) { /* * Read directory entry. @@ -183,6 +188,10 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) size = le16_to_cpu(dire->size) + 1; + /* size should never be larger than SQUASHFS_NAME_LEN */ + if (size > SQUASHFS_NAME_LEN) + goto failed_read; + err = squashfs_read_metadata(inode->i_sb, dire->name, &block, &offset, size); if (err < 0) diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c index 7a9464d08cf6..5d922a6701ab 100644 --- a/fs/squashfs/namei.c +++ b/fs/squashfs/namei.c @@ -176,6 +176,11 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry, length += sizeof(dirh); dir_count = le32_to_cpu(dirh.count) + 1; + + /* dir_count should never be larger than 256 */ + if (dir_count > 256) + goto data_error; + while (dir_count--) { /* * Read directory entry. @@ -187,6 +192,10 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry, size = le16_to_cpu(dire->size) + 1; + /* size should never be larger than SQUASHFS_NAME_LEN */ + if (size > SQUASHFS_NAME_LEN) + goto data_error; + err = squashfs_read_metadata(dir->i_sb, dire->name, &block, &offset, size); if (err < 0) @@ -228,6 +237,9 @@ exit_lookup: d_add(dentry, inode); return ERR_PTR(0); +data_error: + err = -EIO; + read_failure: ERROR("Unable to read directory block [%llx:%x]\n", squashfs_i(dir)->start + msblk->directory_table, -- cgit v1.2.3 From 61de8898a1dc81b0f58f2b3bbc60917a375bc45f Mon Sep 17 00:00:00 2001 From: "Philip A. Prindeville" Date: Wed, 30 Mar 2011 12:59:26 +0000 Subject: atm/solos-pci: Don't include frame pseudo-header on transmit hex-dump commit 18b429e74eeafe42e947b1b0f9a760c7153a0b5c upstream. Omit pkt_hdr preamble when dumping transmitted packet as hex-dump; we can pull this up because the frame has already been sent, and dumping it is the last thing we do with it before freeing it. Also include the size, vpi, and vci in the debug as is done on receive. Use "port" consistently instead of "device" intermittently. Signed-off-by: Philip Prindeville Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/atm/solos-pci.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 36134221abd4..6ba851bafb49 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -695,7 +695,7 @@ void solos_bh(unsigned long card_arg) size); } if (atmdebug) { - dev_info(&card->dev->dev, "Received: device %d\n", port); + dev_info(&card->dev->dev, "Received: port %d\n", port); dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n", size, le16_to_cpu(header->vpi), le16_to_cpu(header->vci)); @@ -1015,8 +1015,15 @@ static uint32_t fpga_tx(struct solos_card *card) /* Clean up and free oldskb now it's gone */ if (atmdebug) { + struct pkt_hdr *header = (void *)oldskb->data; + int size = le16_to_cpu(header->size); + + skb_pull(oldskb, sizeof(*header)); dev_info(&card->dev->dev, "Transmitted: port %d\n", port); + dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n", + size, le16_to_cpu(header->vpi), + le16_to_cpu(header->vci)); print_buffer(oldskb); } -- cgit v1.2.3 From 091bfbbc8a7da176d4553bff8e7d29736599017e Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Mon, 4 Apr 2011 15:40:24 -0400 Subject: ext4: fix credits computing for indirect mapped files commit 5b41395fcc0265fc9f193aef9df39ce49d64677c upstream. When writing a contiguous set of blocks, two indirect blocks could be needed depending on how the blocks are aligned, so we need to increase the number of credits needed by one. [ Also fixed a another bug which could further underestimate the number of journal credits needed by 1; the code was using integer division instead of DIV_ROUND_UP() -- tytso] Signed-off-by: Yongqiang Yang Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ext4/inode.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 3fb64b9e47c4..0595b8cf0178 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -5593,13 +5593,12 @@ static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks, /* if nrblocks are contiguous */ if (chunk) { /* - * With N contiguous data blocks, it need at most - * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) indirect blocks - * 2 dindirect blocks - * 1 tindirect block + * With N contiguous data blocks, we need at most + * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) + 1 indirect blocks, + * 2 dindirect blocks, and 1 tindirect block */ - indirects = nrblocks / EXT4_ADDR_PER_BLOCK(inode->i_sb); - return indirects + 3; + return DIV_ROUND_UP(nrblocks, + EXT4_ADDR_PER_BLOCK(inode->i_sb)) + 4; } /* * if nrblocks are not contiguous, worse case, each block touch -- cgit v1.2.3 From 6e7fd0751dea4c3472f0a1f7b58d0b1ea53fbd84 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 24 Mar 2011 22:51:14 -0400 Subject: nfsd: fix auth_domain reference leak on nlm operations commit 954032d2527f2fce7355ba70709b5e143d6b686f upstream. This was noticed by users who performed more than 2^32 lock operations and hence made this counter overflow (eventually leading to use-after-free's). Setting rq_client to NULL here means that it won't later get auth_domain_put() when it should be. Appears to have been introduced in 2.5.42 by "[PATCH] kNFSd: Move auth domain lookup into svcauth" which moved most of the rq_client handling to common svcauth code, but left behind this one line. Cc: Neil Brown Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfsd/lockd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c index 0c6d81670137..7c831a2731fa 100644 --- a/fs/nfsd/lockd.c +++ b/fs/nfsd/lockd.c @@ -38,7 +38,6 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp) exp_readlock(); nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp); fh_put(&fh); - rqstp->rq_client = NULL; exp_readunlock(); /* We return nlm error codes as nlm doesn't know * about nfsd, but nfsd does know about nlm.. -- cgit v1.2.3 From 153e4ee16df4ec1660a97c6040715e5993f9032e Mon Sep 17 00:00:00 2001 From: Kulikov Vasiliy Date: Sun, 31 Oct 2010 07:10:32 +0000 Subject: net: tipc: fix information leak to userland commit 88f8a5e3e7defccd3925cabb1ee4d3994e5cdb52 upstream. Structure sockaddr_tipc is copied to userland with padding bytes after "id" field in union field "name" unitialized. It leads to leaking of contents of kernel stack memory. We have to initialize them to zero. Signed-off-by: Vasiliy Kulikov Signed-off-by: David S. Miller Signed-off-by: Andi Kleen Cc: Moritz Muehlenhoff Signed-off-by: Greg Kroah-Hartman --- net/tipc/socket.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 66e889ba48fd..1a5f62ab62e7 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -395,6 +395,7 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr, struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; struct tipc_sock *tsock = tipc_sk(sock->sk); + memset(addr, 0, sizeof(*addr)); if (peer) { if ((sock->state != SS_CONNECTED) && ((peer != 2) || (sock->state != SS_DISCONNECTING))) -- cgit v1.2.3 From 58c373ba73707261ace8a2227a7ec99d58e9fd94 Mon Sep 17 00:00:00 2001 From: Nelson Elhage Date: Wed, 3 Nov 2010 16:35:41 +0000 Subject: inet_diag: Make sure we actually run the same bytecode we audited. commit 22e76c849d505d87c5ecf3d3e6742a65f0ff4860 upstream. We were using nlmsg_find_attr() to look up the bytecode by attribute when auditing, but then just using the first attribute when actually running bytecode. So, if we received a message with two attribute elements, where only the second had type INET_DIAG_REQ_BYTECODE, we would validate and run different bytecode strings. Fix this by consistently using nlmsg_find_attr everywhere. [AK: Add const to nlmsg_find_attr to fix new warning] Signed-off-by: Nelson Elhage Signed-off-by: Thomas Graf Signed-off-by: David S. Miller Signed-off-by: Andi Kleen [jmm: Slightly adapted to apply against 2.6.32] Cc: Moritz Muehlenhoff Signed-off-by: Greg Kroah-Hartman --- include/net/netlink.h | 2 +- net/ipv4/inet_diag.c | 27 ++++++++++++++++----------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/include/net/netlink.h b/include/net/netlink.h index 4fc05b58503e..28c27d16c936 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -384,7 +384,7 @@ static inline int nlmsg_parse(const struct nlmsghdr *nlh, int hdrlen, * * Returns the first attribute which matches the specified type. */ -static inline struct nlattr *nlmsg_find_attr(struct nlmsghdr *nlh, +static inline struct nlattr *nlmsg_find_attr(const struct nlmsghdr *nlh, int hdrlen, int attrtype) { return nla_find(nlmsg_attrdata(nlh, hdrlen), diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index e5fa2ddce320..7403b9bf1026 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -490,9 +490,11 @@ static int inet_csk_diag_dump(struct sock *sk, { struct inet_diag_req *r = NLMSG_DATA(cb->nlh); - if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) { + if (nlmsg_attrlen(cb->nlh, sizeof(*r))) { struct inet_diag_entry entry; - struct rtattr *bc = (struct rtattr *)(r + 1); + const struct nlattr *bc = nlmsg_find_attr(cb->nlh, + sizeof(*r), + INET_DIAG_REQ_BYTECODE); struct inet_sock *inet = inet_sk(sk); entry.family = sk->sk_family; @@ -512,7 +514,7 @@ static int inet_csk_diag_dump(struct sock *sk, entry.dport = ntohs(inet->inet_dport); entry.userlocks = sk->sk_userlocks; - if (!inet_diag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), &entry)) + if (!inet_diag_bc_run(nla_data(bc), nla_len(bc), &entry)) return 0; } @@ -527,9 +529,11 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, { struct inet_diag_req *r = NLMSG_DATA(cb->nlh); - if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) { + if (nlmsg_attrlen(cb->nlh, sizeof(*r))) { struct inet_diag_entry entry; - struct rtattr *bc = (struct rtattr *)(r + 1); + const struct nlattr *bc = nlmsg_find_attr(cb->nlh, + sizeof(*r), + INET_DIAG_REQ_BYTECODE); entry.family = tw->tw_family; #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) @@ -548,7 +552,7 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, entry.dport = ntohs(tw->tw_dport); entry.userlocks = 0; - if (!inet_diag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), &entry)) + if (!inet_diag_bc_run(nla_data(bc), nla_len(bc), &entry)) return 0; } @@ -618,7 +622,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, struct inet_diag_req *r = NLMSG_DATA(cb->nlh); struct inet_connection_sock *icsk = inet_csk(sk); struct listen_sock *lopt; - struct rtattr *bc = NULL; + const struct nlattr *bc = NULL; struct inet_sock *inet = inet_sk(sk); int j, s_j; int reqnum, s_reqnum; @@ -638,8 +642,9 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, if (!lopt || !lopt->qlen) goto out; - if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) { - bc = (struct rtattr *)(r + 1); + if (nlmsg_attrlen(cb->nlh, sizeof(*r))) { + bc = nlmsg_find_attr(cb->nlh, sizeof(*r), + INET_DIAG_REQ_BYTECODE); entry.sport = inet->inet_num; entry.userlocks = sk->sk_userlocks; } @@ -672,8 +677,8 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, &ireq->rmt_addr; entry.dport = ntohs(ireq->rmt_port); - if (!inet_diag_bc_run(RTA_DATA(bc), - RTA_PAYLOAD(bc), &entry)) + if (!inet_diag_bc_run(nla_data(bc), + nla_len(bc), &entry)) continue; } -- cgit v1.2.3 From eca877d1ae4a597ff1f213396662690143d01f88 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 22 Dec 2010 13:58:27 +0000 Subject: irda: prevent integer underflow in IRLMP_ENUMDEVICES commit fdac1e0697356ac212259f2147aa60c72e334861 upstream. If the user-provided len is less than the expected offset, the IRLMP_ENUMDEVICES getsockopt will do a copy_to_user() with a very large size value. While this isn't be a security issue on x86 because it will get caught by the access_ok() check, it may leak large amounts of kernel heap on other architectures. In any event, this patch fixes it. Signed-off-by: Dan Rosenberg Signed-off-by: David S. Miller Signed-off-by: Andi Kleen Cc: Moritz Muehlenhoff Signed-off-by: Greg Kroah-Hartman --- net/irda/af_irda.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index fd55b5135de5..83ef96eda75a 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -2278,6 +2278,14 @@ static int __irda_getsockopt(struct socket *sock, int level, int optname, switch (optname) { case IRLMP_ENUMDEVICES: + + /* Offset to first device entry */ + offset = sizeof(struct irda_device_list) - + sizeof(struct irda_device_info); + + if (len < offset) + return -EINVAL; + /* Ask lmp for the current discovery log */ discoveries = irlmp_get_discoveries(&list.len, self->mask.word, self->nslots); @@ -2287,15 +2295,9 @@ static int __irda_getsockopt(struct socket *sock, int level, int optname, err = 0; /* Write total list length back to client */ - if (copy_to_user(optval, &list, - sizeof(struct irda_device_list) - - sizeof(struct irda_device_info))) + if (copy_to_user(optval, &list, offset)) err = -EFAULT; - /* Offset to first device entry */ - offset = sizeof(struct irda_device_list) - - sizeof(struct irda_device_info); - /* Copy the list itself - watch for overflow */ if(list.len > 2048) { -- cgit v1.2.3 From 4d9566dc782ea4c60c44f3d6ee8e982061967c90 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Sun, 26 Dec 2010 06:54:53 +0000 Subject: CAN: Use inode instead of kernel address for /proc file commit 9f260e0efa4766e56d0ac14f1aeea6ee5eb8fe83 upstream. Since the socket address is just being used as a unique identifier, its inode number is an alternative that does not leak potentially sensitive information. CC-ing stable because MITRE has assigned CVE-2010-4565 to the issue. Signed-off-by: Dan Rosenberg Acked-by: Oliver Hartkopp Signed-off-by: David S. Miller Signed-off-by: Andi Kleen Cc: Moritz Muehlenhoff Signed-off-by: Greg Kroah-Hartman --- net/can/bcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/can/bcm.c b/net/can/bcm.c index 6faa8256e10c..9d5e8accfab1 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -125,7 +125,7 @@ struct bcm_sock { struct list_head tx_ops; unsigned long dropped_usr_msgs; struct proc_dir_entry *bcm_proc_read; - char procname [20]; /* pointer printed in ASCII with \0 */ + char procname [32]; /* inode number in decimal with \0 */ }; static inline struct bcm_sock *bcm_sk(const struct sock *sk) @@ -1521,7 +1521,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len, if (proc_dir) { /* unique socket address as filename */ - sprintf(bo->procname, "%p", sock); + sprintf(bo->procname, "%lu", sock_i_ino(sk)); bo->bcm_proc_read = proc_create_data(bo->procname, 0644, proc_dir, &bcm_proc_fops, sk); -- cgit v1.2.3 From 33b1b26d48822cbe04d14ba255672ed5ecadb3da Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 28 Oct 2010 15:40:55 +0000 Subject: net: fix rds_iovec page count overflow commit 1b1f693d7ad6d193862dcb1118540a030c5e761f upstream. As reported by Thomas Pollet, the rdma page counting can overflow. We get the rdma sizes in 64-bit unsigned entities, but then limit it to UINT_MAX bytes and shift them down to pages (so with a possible "+1" for an unaligned address). So each individual page count fits comfortably in an 'unsigned int' (not even close to overflowing into signed), but as they are added up, they might end up resulting in a signed return value. Which would be wrong. Catch the case of tot_pages turning negative, and return the appropriate error code. Reported-by: Thomas Pollet Signed-off-by: Linus Torvalds Signed-off-by: Andy Grover Signed-off-by: David S. Miller Signed-off-by: Andi Kleen [v2: nr is unsigned in the old code] Signed-off-by: Stefan Bader Acked-by: Tim Gardner Acked-by: Brad Figg Signed-off-by: Greg Kroah-Hartman --- net/rds/rdma.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/net/rds/rdma.c b/net/rds/rdma.c index 39989678c2d2..e2ccf7b4e497 100644 --- a/net/rds/rdma.c +++ b/net/rds/rdma.c @@ -500,6 +500,17 @@ static struct rds_rdma_op *rds_rdma_prepare(struct rds_sock *rs, max_pages = max(nr, max_pages); nr_pages += nr; + + /* + * nr for one entry in limited to (UINT_MAX>>PAGE_SHIFT)+1 + * so nr_pages cannot overflow without becoming bigger than + * INT_MAX first. If nr cannot overflow then max_pages should + * be ok. + */ + if (nr_pages > INT_MAX) { + ret = -EINVAL; + goto out; + } } pages = kcalloc(max_pages, sizeof(struct page *), GFP_KERNEL); -- cgit v1.2.3 From c797893cd1108165fcd7dac1d0954fcc5b6e6ec6 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 1 Mar 2011 17:50:00 +0000 Subject: xfs: zero proper structure size for geometry calls commit af24ee9ea8d532e16883251a6684dfa1be8eec29 upstream. Commit 493f3358cb289ccf716c5a14fa5bb52ab75943e5 added this call to xfs_fs_geometry() in order to avoid passing kernel stack data back to user space: + memset(geo, 0, sizeof(*geo)); Unfortunately, one of the callers of that function passes the address of a smaller data type, cast to fit the type that xfs_fs_geometry() requires. As a result, this can happen: Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: f87aca93 Pid: 262, comm: xfs_fsr Not tainted 2.6.38-rc6-493f3358cb2+ #1 Call Trace: [] ? panic+0x50/0x150 [] ? __stack_chk_fail+0x10/0x18 [] ? xfs_ioc_fsgeometry_v1+0x56/0x5d [xfs] Fix this by fixing that one caller to pass the right type and then copy out the subset it is interested in. Note: This patch is an alternative to one originally proposed by Eric Sandeen. Reported-by: Jeffrey Hundstad Signed-off-by: Alex Elder Signed-off-by: Andi Kleen Reviewed-by: Eric Sandeen Tested-by: Jeffrey Hundstad Signed-off-by: Greg Kroah-Hartman --- fs/xfs/linux-2.6/xfs_ioctl.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 82a74f6142f8..0a3eb18fc70c 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -703,14 +703,19 @@ xfs_ioc_fsgeometry_v1( xfs_mount_t *mp, void __user *arg) { - xfs_fsop_geom_v1_t fsgeo; + xfs_fsop_geom_t fsgeo; int error; - error = xfs_fs_geometry(mp, (xfs_fsop_geom_t *)&fsgeo, 3); + error = xfs_fs_geometry(mp, &fsgeo, 3); if (error) return -error; - if (copy_to_user(arg, &fsgeo, sizeof(fsgeo))) + /* + * Caller should have passed an argument of type + * xfs_fsop_geom_v1_t. This is a proper subset of the + * xfs_fsop_geom_t that xfs_fs_geometry() fills in. + */ + if (copy_to_user(arg, &fsgeo, sizeof(xfs_fsop_geom_v1_t))) return -XFS_ERROR(EFAULT); return 0; } -- cgit v1.2.3 From 0696d0df97fc59f0de7ba8fca98f4f47d62acd4e Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 14 Mar 2011 13:48:08 -0400 Subject: cifs: always do is_path_accessible check in cifs_mount commit 70945643722ffeac779d2529a348f99567fa5c33 upstream. Currently, we skip doing the is_path_accessible check in cifs_mount if there is no prefixpath. I have a report of at least one server however that allows a TREE_CONNECT to a share that has a DFS referral at its root. The reporter in this case was using a UNC that had no prefixpath, so the is_path_accessible check was not triggered and the box later hit a BUG() because we were chasing a DFS referral on the root dentry for the mount. This patch fixes this by removing the check for a zero-length prefixpath. That should make the is_path_accessible check be done in this situation and should allow the client to chase the DFS referral at mount time instead. Reported-and-Tested-by: Yogesh Sharma Signed-off-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/cifs/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index fa1039a7ac40..50d60cc80ce8 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2606,7 +2606,7 @@ try_mount_again: remote_path_check: /* check if a whole path (including prepath) is not remote */ - if (!rc && cifs_sb->prepathlen && tcon) { + if (!rc && tcon) { /* build_path_to_root works only when we have a valid tcon */ full_path = cifs_build_path_to_root(cifs_sb); if (full_path == NULL) { -- cgit v1.2.3 From 347d0613b1c4422421a88b00d411b18eb3baa9ac Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Fri, 4 Feb 2011 09:23:33 -0300 Subject: video: sn9c102: world-wirtable sysfs files commit 14ddc3188d50855ae2a419a6aced995e2834e5d4 upstream. Don't allow everybody to change video settings. Signed-off-by: Vasiliy Kulikov Acked-by: Mauro Carvalho Chehab Acked-by: Luca Risolia Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/media/video/sn9c102/sn9c102_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 28e19daadec9..5c9587a81a4b 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -1430,9 +1430,9 @@ static DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, sn9c102_show_i2c_reg, sn9c102_store_i2c_reg); static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, sn9c102_show_i2c_val, sn9c102_store_i2c_val); -static DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green); -static DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue); -static DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red); +static DEVICE_ATTR(green, S_IWUSR, NULL, sn9c102_store_green); +static DEVICE_ATTR(blue, S_IWUSR, NULL, sn9c102_store_blue); +static DEVICE_ATTR(red, S_IWUSR, NULL, sn9c102_store_red); static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL); -- cgit v1.2.3 From b9d68407049fa7bada4dc580f5a225055ef6ed5d Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Fri, 4 Feb 2011 15:24:19 +0300 Subject: UBIFS: restrict world-writable debugfs files commit 8c559d30b4e59cf6994215ada1fe744928f494bf upstream. Don't allow everybody to dump sensitive information about filesystems. Signed-off-by: Vasiliy Kulikov Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ubifs/debug.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 923d697a302a..a0c09fc49962 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -2687,19 +2687,19 @@ int dbg_debugfs_init_fs(struct ubifs_info *c) } fname = "dump_lprops"; - dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); + dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); if (IS_ERR(dent)) goto out_remove; d->dfs_dump_lprops = dent; fname = "dump_budg"; - dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); + dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); if (IS_ERR(dent)) goto out_remove; d->dfs_dump_budg = dent; fname = "dump_tnc"; - dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); + dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); if (IS_ERR(dent)) goto out_remove; d->dfs_dump_tnc = dent; -- cgit v1.2.3 From 49a57ca87515571338f2f541ff5726cab004a337 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sun, 13 Mar 2011 06:54:31 +0000 Subject: NET: cdc-phonet, handle empty phonet header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 468c3f924f043cad7a04f4f4d5224a2c9bc886c1 upstream. Currently, for N 5800 XM I get: cdc_phonet: probe of 1-6:1.10 failed with error -22 It's because phonet_header is empty. Extra altsetting looks like there: E 05 24 00 01 10 03 24 ab 05 24 06 0a 0b 04 24 fd .$....$..$....$. E 00 . I don't see the header used anywhere so just check if the phonet descriptor is there, not the structure itself. Signed-off-by: Jiri Slaby Signed-off-by: Andi Kleen Cc: Rémi Denis-Courmont Cc: David S. Miller Acked-by: Rémi Denis-Courmont Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/cdc-phonet.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c index dc9444525b49..b18cda45e140 100644 --- a/drivers/net/usb/cdc-phonet.c +++ b/drivers/net/usb/cdc-phonet.c @@ -326,13 +326,13 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id) { static const char ifname[] = "usbpn%d"; const struct usb_cdc_union_desc *union_header = NULL; - const struct usb_cdc_header_desc *phonet_header = NULL; const struct usb_host_interface *data_desc; struct usb_interface *data_intf; struct usb_device *usbdev = interface_to_usbdev(intf); struct net_device *dev; struct usbpn_dev *pnd; u8 *data; + int phonet = 0; int len, err; data = intf->altsetting->extra; @@ -353,10 +353,7 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id) (struct usb_cdc_union_desc *)data; break; case 0xAB: - if (phonet_header || dlen < 5) - break; - phonet_header = - (struct usb_cdc_header_desc *)data; + phonet = 1; break; } } @@ -364,7 +361,7 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id) len -= dlen; } - if (!union_header || !phonet_header) + if (!union_header || !phonet) return -EINVAL; data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0); -- cgit v1.2.3 From 77b51dedbea56d55f44f3f0ea3f47b784cb04106 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 1 Mar 2011 14:28:02 +0000 Subject: x86: Fix a bogus unwind annotation in lib/semaphore_32.S commit e938c287ea8d977e079f07464ac69923412663ce upstream. 'simple' would have required specifying current frame address and return address location manually, but that's obviously not the case (and not necessary) here. Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen LKML-Reference: <4D6D1082020000780003454C@vpn.id2.novell.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/lib/semaphore_32.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/lib/semaphore_32.S b/arch/x86/lib/semaphore_32.S index 648fe4741782..f35eec78a68e 100644 --- a/arch/x86/lib/semaphore_32.S +++ b/arch/x86/lib/semaphore_32.S @@ -36,7 +36,7 @@ */ #ifdef CONFIG_SMP ENTRY(__write_lock_failed) - CFI_STARTPROC simple + CFI_STARTPROC FRAME 2: LOCK_PREFIX addl $ RW_LOCK_BIAS,(%eax) -- cgit v1.2.3 From 386797ea0e4eb044f6c7433c15d75cb4120f73a7 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Thu, 24 Feb 2011 15:33:24 -0500 Subject: tioca: Fix assignment from incompatible pointer warnings commit b4a6b3436531f6c5256e6d60d388c3c28ff1a0e9 upstream. The prototype for sn_pci_provider->{dma_map,dma_map_consistent} expects an unsigned long instead of a u64. Signed-off-by: Jeff Mahoney Signed-off-by: Tony Luck Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/ia64/sn/pci/tioca_provider.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index 4d4536e3b6f3..9c271be9919a 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c @@ -509,7 +509,7 @@ tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) * use the GART mapped mode. */ static u64 -tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags) +tioca_dma_map(struct pci_dev *pdev, unsigned long paddr, size_t byte_count, int dma_flags) { u64 mapaddr; -- cgit v1.2.3 From 1ad8267b5d86dce44f538953dab1944c0b6bf032 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Thu, 24 Feb 2011 17:23:09 -0500 Subject: mca.c: Fix cast from integer to pointer warning commit c1d036c4d1cb00b7e8473a2ad0a78f13e13a8183 upstream. ia64_mca_cpu_init has a void *data local variable that is assigned the value from either __get_free_pages() or mca_bootmem(). The problem is that __get_free_pages returns an unsigned long and mca_bootmem, via alloc_bootmem(), returns a void *. format_mca_init_stack takes the void *, and it's also used with __pa(), but that casts it to long anyway. This results in the following build warning: arch/ia64/kernel/mca.c:1898: warning: assignment makes pointer from integer without a cast Cast the return of __get_free_pages to a void * to avoid the warning. Signed-off-by: Jeff Mahoney Signed-off-by: Tony Luck Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/ia64/kernel/mca.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index a0220dc5ff42..6871c1bb0579 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -1859,7 +1859,8 @@ ia64_mca_cpu_init(void *cpu_data) data = mca_bootmem(); first_time = 0; } else - data = __get_free_pages(GFP_KERNEL, get_order(sz)); + data = (void *)__get_free_pages(GFP_KERNEL, + get_order(sz)); if (!data) panic("Could not allocate MCA memory for cpu %d\n", cpu); -- cgit v1.2.3 From b83ab1f39a78cd10c4512bfaf7642cf98c818788 Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Thu, 14 Apr 2011 15:22:20 -0700 Subject: ramfs: fix memleak on no-mmu arch commit b836aec53e2bce71de1d5415313380688c851477 upstream. On no-mmu arch, there is a memleak during shmem test. The cause of this memleak is ramfs_nommu_expand_for_mapping() added page refcount to 2 which makes iput() can't free that pages. The simple test file is like this: int main(void) { int i; key_t k = ftok("/etc", 42); for ( i=0; i<100; ++i) { int id = shmget(k, 10000, 0644|IPC_CREAT); if (id == -1) { printf("shmget error\n"); } if(shmctl(id, IPC_RMID, NULL ) == -1) { printf("shm rm error\n"); return -1; } } printf("run ok...\n"); return 0; } And the result: root:/> free total used free shared buffers Mem: 60320 17912 42408 0 0 -/+ buffers: 17912 42408 root:/> shmem run ok... root:/> free total used free shared buffers Mem: 60320 19096 41224 0 0 -/+ buffers: 19096 41224 root:/> shmem run ok... root:/> free total used free shared buffers Mem: 60320 20296 40024 0 0 -/+ buffers: 20296 40024 ... After this patch the test result is:(no memleak anymore) root:/> free total used free shared buffers Mem: 60320 16668 43652 0 0 -/+ buffers: 16668 43652 root:/> shmem run ok... root:/> free total used free shared buffers Mem: 60320 16668 43652 0 0 -/+ buffers: 16668 43652 Signed-off-by: Bob Liu Acked-by: Hugh Dickins Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ramfs/file-nommu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index d532c20fc179..9bfb81b8bffa 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c @@ -112,6 +112,7 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) SetPageDirty(page); unlock_page(page); + put_page(page); } return 0; -- cgit v1.2.3 From d8d3d0e28304d3ed22f33ec8d1cfab54e7946d79 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 14 Apr 2011 15:22:07 -0700 Subject: MAINTAINERS: update STABLE BRANCH info commit d00ebeac5f24f290636f7a895dafc124b2930a08 upstream. Drop Chris Wright from STABLE maintainers. He hasn't done STABLE release work for quite some time. Signed-off-by: Randy Dunlap Acked-by: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 02f75fccac20..696e7d216bb6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5442,7 +5442,6 @@ F: arch/alpha/kernel/srm_env.c STABLE BRANCH M: Greg Kroah-Hartman -M: Chris Wright L: stable@kernel.org S: Maintained -- cgit v1.2.3 From bd1ad0b2ef08f8c6e42bfd356d7666bca6e2bfcb Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 13 Apr 2011 10:31:52 +0300 Subject: UBIFS: fix oops when R/O file-system is fsync'ed commit 78530bf7f2559b317c04991b52217c1608d5a58d upstream. This patch fixes severe UBIFS bug: UBIFS oopses when we 'fsync()' an file on R/O-mounter file-system. We (the UBIFS authors) incorrectly thought that VFS would not propagate 'fsync()' down to the file-system if it is read-only, but this is not the case. It is easy to exploit this bug using the following simple perl script: use strict; use File::Sync qw(fsync sync); die "File path is not specified" if not defined $ARGV[0]; my $path = $ARGV[0]; open FILE, "<", "$path" or die "Cannot open $path: $!"; fsync(\*FILE) or die "cannot fsync $path: $!"; close FILE or die "Cannot close $path: $!"; Thanks to Reuben Dowle for reporting about this issue. Signed-off-by: Artem Bityutskiy Signed-off-by: Andi Kleen Reported-by: Reuben Dowle Signed-off-by: Greg Kroah-Hartman --- fs/ubifs/file.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 12f445cee9f7..47f55ea9ddad 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -1315,6 +1315,9 @@ int ubifs_fsync(struct file *file, int datasync) dbg_gen("syncing inode %lu", inode->i_ino); + if (inode->i_sb->s_flags & MS_RDONLY) + return 0; + /* * VFS has already synchronized dirty pages for this inode. Synchronize * the inode unless this is a 'datasync()' call. -- cgit v1.2.3 From 22e086770c43e105b0f64eef88752fea39a3c68c Mon Sep 17 00:00:00 2001 From: Hans Rosenfeld Date: Wed, 28 Jul 2010 19:09:30 +0200 Subject: x86, cpu: AMD errata checking framework commit d78d671db478eb8b14c78501c0cee1cc7baf6967 upstream. Errata are defined using the AMD_LEGACY_ERRATUM() or AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that have an OSVW id assigned, which it takes as first argument. Both take a variable number of family-specific model-stepping ranges created by AMD_MODEL_RANGE(). Iff an erratum has an OSVW id, OSVW is available on the CPU, and the OSVW id is known to the hardware, it is used to determine whether an erratum is present. Otherwise, the model-stepping ranges are matched against the current CPU to find out whether the erratum applies. For certain special errata, the code using this framework might have to conduct further checks to make sure an erratum is really (not) present. Signed-off-by: Hans Rosenfeld Signed-off-by: Andi Kleen LKML-Reference: <1280336972-865982-1-git-send-email-hans.rosenfeld@amd.com> Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/processor.h | 18 ++++++++++++ arch/x86/kernel/cpu/amd.c | 60 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index eccaebc632d1..72397a7cb301 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -1002,4 +1002,22 @@ unsigned long calc_aperfmperf_ratio(struct aperfmperf *old, return ratio; } +/* + * AMD errata checking + */ +#ifdef CONFIG_CPU_SUP_AMD +extern bool cpu_has_amd_erratum(const int *); + +#define AMD_LEGACY_ERRATUM(...) { -1, __VA_ARGS__, 0 } +#define AMD_OSVW_ERRATUM(osvw_id, ...) { osvw_id, __VA_ARGS__, 0 } +#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \ + ((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end)) +#define AMD_MODEL_RANGE_FAMILY(range) (((range) >> 24) & 0xff) +#define AMD_MODEL_RANGE_START(range) (((range) >> 12) & 0xfff) +#define AMD_MODEL_RANGE_END(range) ((range) & 0xfff) + +#else +#define cpu_has_amd_erratum(x) (false) +#endif /* CONFIG_CPU_SUP_AMD */ + #endif /* _ASM_X86_PROCESSOR_H */ diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index d11629a89b03..b283b772ef68 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -608,3 +608,63 @@ static const struct cpu_dev __cpuinitconst amd_cpu_dev = { }; cpu_dev_register(amd_cpu_dev); + +/* + * AMD errata checking + * + * Errata are defined as arrays of ints using the AMD_LEGACY_ERRATUM() or + * AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that + * have an OSVW id assigned, which it takes as first argument. Both take a + * variable number of family-specific model-stepping ranges created by + * AMD_MODEL_RANGE(). Each erratum also has to be declared as extern const + * int[] in arch/x86/include/asm/processor.h. + * + * Example: + * + * const int amd_erratum_319[] = + * AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0x4, 0x2), + * AMD_MODEL_RANGE(0x10, 0x8, 0x0, 0x8, 0x0), + * AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0)); + */ + +bool cpu_has_amd_erratum(const int *erratum) +{ + struct cpuinfo_x86 *cpu = ¤t_cpu_data; + int osvw_id = *erratum++; + u32 range; + u32 ms; + + /* + * If called early enough that current_cpu_data hasn't been initialized + * yet, fall back to boot_cpu_data. + */ + if (cpu->x86 == 0) + cpu = &boot_cpu_data; + + if (cpu->x86_vendor != X86_VENDOR_AMD) + return false; + + if (osvw_id >= 0 && osvw_id < 65536 && + cpu_has(cpu, X86_FEATURE_OSVW)) { + u64 osvw_len; + + rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, osvw_len); + if (osvw_id < osvw_len) { + u64 osvw_bits; + + rdmsrl(MSR_AMD64_OSVW_STATUS + (osvw_id >> 6), + osvw_bits); + return osvw_bits & (1ULL << (osvw_id & 0x3f)); + } + } + + /* OSVW unavailable or ID unknown, match family-model-stepping range */ + ms = (cpu->x86_model << 8) | cpu->x86_mask; + while ((range = *erratum++)) + if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) && + (ms >= AMD_MODEL_RANGE_START(range)) && + (ms <= AMD_MODEL_RANGE_END(range))) + return true; + + return false; +} -- cgit v1.2.3 From 5b6a0df7eaf9c516bd018f056fe336b941fad165 Mon Sep 17 00:00:00 2001 From: Hans Rosenfeld Date: Wed, 28 Jul 2010 19:09:31 +0200 Subject: x86, cpu: Clean up AMD erratum 400 workaround commit 9d8888c2a214aece2494a49e699a097c2ba9498b upstream. Remove check_c1e_idle() and use the new AMD errata checking framework instead. Signed-off-by: Hans Rosenfeld Signed-off-by: Andi Kleen LKML-Reference: <1280336972-865982-2-git-send-email-hans.rosenfeld@amd.com> Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/processor.h | 1 + arch/x86/kernel/cpu/amd.c | 5 +++++ arch/x86/kernel/process.c | 39 ++------------------------------------- 3 files changed, 8 insertions(+), 37 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 72397a7cb301..2fe362c72eb0 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -1006,6 +1006,7 @@ unsigned long calc_aperfmperf_ratio(struct aperfmperf *old, * AMD errata checking */ #ifdef CONFIG_CPU_SUP_AMD +extern const int amd_erratum_400[]; extern bool cpu_has_amd_erratum(const int *); #define AMD_LEGACY_ERRATUM(...) { -1, __VA_ARGS__, 0 } diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index b283b772ef68..35a1d17e35de 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -627,6 +627,11 @@ cpu_dev_register(amd_cpu_dev); * AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0)); */ +const int amd_erratum_400[] = + AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf), + AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf)); + + bool cpu_has_amd_erratum(const int *erratum) { struct cpuinfo_x86 *cpu = ¤t_cpu_data; diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index e7e35219b32f..553b02f13094 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -525,42 +525,6 @@ static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c) return (edx & MWAIT_EDX_C1); } -/* - * Check for AMD CPUs, where APIC timer interrupt does not wake up CPU from C1e. - * For more information see - * - Erratum #400 for NPT family 0xf and family 0x10 CPUs - * - Erratum #365 for family 0x11 (not affected because C1e not in use) - */ -static int __cpuinit check_c1e_idle(const struct cpuinfo_x86 *c) -{ - u64 val; - if (c->x86_vendor != X86_VENDOR_AMD) - goto no_c1e_idle; - - /* Family 0x0f models < rev F do not have C1E */ - if (c->x86 == 0x0F && c->x86_model >= 0x40) - return 1; - - if (c->x86 == 0x10) { - /* - * check OSVW bit for CPUs that are not affected - * by erratum #400 - */ - if (cpu_has(c, X86_FEATURE_OSVW)) { - rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, val); - if (val >= 2) { - rdmsrl(MSR_AMD64_OSVW_STATUS, val); - if (!(val & BIT(1))) - goto no_c1e_idle; - } - } - return 1; - } - -no_c1e_idle: - return 0; -} - static cpumask_var_t c1e_mask; static int c1e_detected; @@ -638,7 +602,8 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) */ printk(KERN_INFO "using mwait in idle threads.\n"); pm_idle = mwait_idle; - } else if (check_c1e_idle(c)) { + } else if (cpu_has_amd_erratum(amd_erratum_400)) { + /* E400: APIC timer interrupt does not wake up CPU from C1e */ printk(KERN_INFO "using C1E aware idle routine\n"); pm_idle = c1e_idle; } else -- cgit v1.2.3 From f6325b0c59f6a6ee4ba009c415c7fd3c8f08b513 Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Tue, 15 Mar 2011 12:13:44 -0400 Subject: x86, AMD: Set ARAT feature on AMD processors commit b87cf80af3ba4b4c008b4face3c68d604e1715c6 upstream. Support for Always Running APIC timer (ARAT) was introduced in commit db954b5898dd3ef3ef93f4144158ea8f97deb058. This feature allows us to avoid switching timers from LAPIC to something else (e.g. HPET) and go into timer broadcasts when entering deep C-states. AMD processors don't provide a CPUID bit for that feature but they also keep APIC timers running in deep C-states (except for cases when the processor is affected by erratum 400). Therefore we should set ARAT feature bit on AMD CPUs. Tested-by: Borislav Petkov Acked-by: Andreas Herrmann Acked-by: Mark Langsdorf Acked-by: Thomas Gleixner Signed-off-by: Boris Ostrovsky Signed-off-by: Andi Kleen LKML-Reference: <1300205624-4813-1-git-send-email-ostr@amd64.org> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/amd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 35a1d17e35de..4e2988c2978a 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -564,6 +564,10 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) } } #endif + + /* As a rule processors have APIC timer running in deep C states */ + if (c->x86 >= 0xf && !cpu_has_amd_erratum(amd_erratum_400)) + set_cpu_cap(c, X86_FEATURE_ARAT); } #ifdef CONFIG_X86_32 -- cgit v1.2.3 From 1a2c7d94b5a0f06387e0c346861ac2f67f07c5ca Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 15 Apr 2011 14:47:40 +0200 Subject: x86, amd: Disable GartTlbWlkErr when BIOS forgets it commit 5bbc097d890409d8eff4e3f1d26f11a9d6b7c07e upstream. This patch disables GartTlbWlk errors on AMD Fam10h CPUs if the BIOS forgets to do is (or is just too old). Letting these errors enabled can cause a sync-flood on the CPU causing a reboot. The AMD BKDG recommends disabling GART TLB Wlk Error completely. This patch is the fix for https://bugzilla.kernel.org/show_bug.cgi?id=33012 on my machine. Signed-off-by: Joerg Roedel Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/20110415131152.GJ18463@8bytes.org Tested-by: Alexandre Demers Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/msr-index.h | 4 ++++ arch/x86/kernel/cpu/amd.c | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 8c7ae4318629..0639d9f2df67 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -85,11 +85,15 @@ #define MSR_IA32_MC0_ADDR 0x00000402 #define MSR_IA32_MC0_MISC 0x00000403 +#define MSR_AMD64_MC0_MASK 0xc0010044 + #define MSR_IA32_MCx_CTL(x) (MSR_IA32_MC0_CTL + 4*(x)) #define MSR_IA32_MCx_STATUS(x) (MSR_IA32_MC0_STATUS + 4*(x)) #define MSR_IA32_MCx_ADDR(x) (MSR_IA32_MC0_ADDR + 4*(x)) #define MSR_IA32_MCx_MISC(x) (MSR_IA32_MC0_MISC + 4*(x)) +#define MSR_AMD64_MCx_MASK(x) (MSR_AMD64_MC0_MASK + (x)) + /* These are consecutive and not in the normal 4er MCE bank block */ #define MSR_IA32_MC0_CTL2 0x00000280 #define MSR_IA32_MCx_CTL2(x) (MSR_IA32_MC0_CTL2 + (x)) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 4e2988c2978a..f98bb34916a9 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -568,6 +568,25 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) /* As a rule processors have APIC timer running in deep C states */ if (c->x86 >= 0xf && !cpu_has_amd_erratum(amd_erratum_400)) set_cpu_cap(c, X86_FEATURE_ARAT); + + /* + * Disable GART TLB Walk Errors on Fam10h. We do this here + * because this is always needed when GART is enabled, even in a + * kernel which has no MCE support built in. + */ + if (c->x86 == 0x10) { + /* + * BIOS should disable GartTlbWlk Errors themself. If + * it doesn't do it here as suggested by the BKDG. + * + * Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33012 + */ + u64 mask; + + rdmsrl(MSR_AMD64_MCx_MASK(4), mask); + mask |= (1 << 10); + wrmsrl(MSR_AMD64_MCx_MASK(4), mask); + } } #ifdef CONFIG_X86_32 -- cgit v1.2.3 From c8bcddad9920fa746e46c2b09ae02fa289757246 Mon Sep 17 00:00:00 2001 From: Christian Simon Date: Mon, 28 Mar 2011 21:54:47 +0200 Subject: USB: ftdi_sio: Added IDs for CTI USB Serial Devices commit 5a9443f08c83c294c5c806a689c1184b27cb26b3 upstream. I added new ProdutIds for two devices from CTI GmbH Leipzig. Signed-off-by: Christian Simon Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/ftdi_sio.c | 2 ++ drivers/usb/serial/ftdi_sio_ids.h | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index b2c4c1c940e8..9b18a6087861 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -150,6 +150,8 @@ static struct ftdi_sio_quirk ftdi_stmclite_quirk = { * /sys/bus/usb/ftdi_sio/new_id, then send patch/report! */ static struct usb_device_id id_table_combined [] = { + { USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 3523df534a27..e5755437a719 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1140,3 +1140,12 @@ #define QIHARDWARE_VID 0x20B7 #define MILKYMISTONE_JTAGSERIAL_PID 0x0713 +/* + * CTI GmbH RS485 Converter http://www.cti-lean.com/ + */ +/* USB-485-Mini*/ +#define FTDI_CTI_MINI_PID 0xF608 +/* USB-Nano-485*/ +#define FTDI_CTI_NANO_PID 0xF60B + + -- cgit v1.2.3 From e17e9da97bca277c34a7a9ceb09c82e55040709c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 8 Apr 2011 17:38:22 +0200 Subject: USB: ftdi_sio: add PID for OCT DK201 docking station commit 11a31d84129dc3133417d626643d714c9df5317e upstream. Add PID 0x0103 for serial port of the OCT DK201 docking station. Reported-by: Jan Hoogenraad Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 9b18a6087861..66ba6069778d 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -526,6 +526,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) }, { USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) }, { USB_DEVICE(OCT_VID, OCT_US101_PID) }, + { USB_DEVICE(OCT_VID, OCT_DK201_PID) }, { USB_DEVICE(FTDI_VID, FTDI_HE_TIRA1_PID), .driver_info = (kernel_ulong_t)&ftdi_HE_TIRA1_quirk }, { USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID), diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index e5755437a719..adad1932ac52 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -572,6 +572,7 @@ /* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */ /* Also rebadged as Dick Smith Electronics (Aus) XH6451 */ /* Also rebadged as SIIG Inc. model US2308 hardware version 1 */ +#define OCT_DK201_PID 0x0103 /* OCT DK201 USB docking station */ #define OCT_US101_PID 0x0421 /* OCT US101 USB to RS-232 */ /* -- cgit v1.2.3 From da7ffa19f5a8e6428a8b01a245cd838aa496ec07 Mon Sep 17 00:00:00 2001 From: Paul Friedrich Date: Fri, 18 Mar 2011 11:13:55 +0100 Subject: USB: ftdi_sio: add ids for Hameg HO720 and HO730 commit c53c2fab40cf16e13af66f40bfd27200cda98d2f upstream. usb serial: ftdi_sio: add two missing USB ID's for Hameg interfaces HO720 and HO730 Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/ftdi_sio.c | 2 ++ drivers/usb/serial/ftdi_sio_ids.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 66ba6069778d..8ed7c888c7d4 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -787,6 +787,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) }, + { USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) }, + { USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) }, { USB_DEVICE(FTDI_VID, HAMEG_HO870_PID) }, { USB_DEVICE(FTDI_VID, MJSG_GENERIC_PID) }, { USB_DEVICE(FTDI_VID, MJSG_SR_RADIO_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index adad1932ac52..0060913edb91 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -300,6 +300,8 @@ * Hameg HO820 and HO870 interface (using VID 0x0403) */ #define HAMEG_HO820_PID 0xed74 +#define HAMEG_HO730_PID 0xed73 +#define HAMEG_HO720_PID 0xed72 #define HAMEG_HO870_PID 0xed71 /* -- cgit v1.2.3 From c5f6106e9d80fbccdc9a7e4827e82076fb3e7570 Mon Sep 17 00:00:00 2001 From: Enrico Mioso Date: Fri, 17 Sep 2010 10:54:23 +0200 Subject: USB: option: Add new ONDA vendor id and product id for ONDA MT825UP commit c6991b6fd2b4201174dc4620d0c8c4f5ff27b36f upstream. This patch, adds to the option driver the Onda Communication (http://www.ondacommunication.com) vendor id, and the MT825UP modem device id. Note that many variants of this same device are being release here in Italy (at least one or two per telephony operator). These devices are perfectly equivalent except for some predefined settings (which can be changed of course). It should be noted that most ONDA devices are allready supported (they used other vendor's ids in the past). The patch seems working fine here, and the rest of the driver seems uninfluenced. Signed-off-by: Enrico Mioso Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/option.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index a0f46c484c68..364edd20b416 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -381,6 +381,12 @@ static void option_instat_callback(struct urb *urb); #define CELOT_VENDOR_ID 0x211f #define CELOT_PRODUCT_CT680M 0x6801 +/* ONDA Communication vendor id */ +#define ONDA_VENDOR_ID 0x1ee8 + +/* ONDA MT825UP HSDPA 14.2 modem */ +#define ONDA_MT825UP 0x000b + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -934,6 +940,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */ + { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); -- cgit v1.2.3 From 7434532fb72b9e5315ba32e1bf6fdb9061f504e0 Mon Sep 17 00:00:00 2001 From: "Marius B. Kotsbak" Date: Tue, 22 Mar 2011 00:01:53 +0100 Subject: USB: option: Added support for Samsung GT-B3730/GT-B3710 LTE USB modem. commit 80f9df3e0093ad9f1eeefd2ff7fd27daaa518d25 upstream. Bind only modem AT command endpoint to option. Signed-off-by: Marius B. Kotsbak Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/option.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 364edd20b416..62109960ebfd 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -387,6 +387,10 @@ static void option_instat_callback(struct urb *urb); /* ONDA MT825UP HSDPA 14.2 modem */ #define ONDA_MT825UP 0x000b +/* Samsung products */ +#define SAMSUNG_VENDOR_ID 0x04e8 +#define SAMSUNG_PRODUCT_GT_B3730 0x6889 + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -941,6 +945,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */ { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */ + { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730/GT-B3710 LTE USB modem.*/ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); -- cgit v1.2.3 From e84891e970ce8baf3c57b5a79d05f52072170052 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 18 Apr 2011 10:35:30 -0700 Subject: next_pidmap: fix overflow condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit c78193e9c7bcbf25b8237ad0dec82f805c4ea69b upstream. next_pidmap() just quietly accepted whatever 'last' pid that was passed in, which is not all that safe when one of the users is /proc. Admittedly the proc code should do some sanity checking on the range (and that will be the next commit), but that doesn't mean that the helper functions should just do that pidmap pointer arithmetic without checking the range of its arguments. So clamp 'last' to PID_MAX_LIMIT. The fact that we then do "last+1" doesn't really matter, the for-loop does check against the end of the pidmap array properly (it's only the actual pointer arithmetic overflow case we need to worry about, and going one bit beyond isn't going to overflow). [ Use PID_MAX_LIMIT rather than pid_max as per Eric Biederman ] Reported-by: Tavis Ormandy Analyzed-by: Robert Święcki Cc: Eric W. Biederman Cc: Pavel Emelyanov Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/linux/pid.h | 2 +- kernel/pid.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/linux/pid.h b/include/linux/pid.h index 49f1c2f66e95..ec9f2df57f1b 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h @@ -117,7 +117,7 @@ extern struct pid *find_vpid(int nr); */ extern struct pid *find_get_pid(int nr); extern struct pid *find_ge_pid(int nr, struct pid_namespace *); -int next_pidmap(struct pid_namespace *pid_ns, int last); +int next_pidmap(struct pid_namespace *pid_ns, unsigned int last); extern struct pid *alloc_pid(struct pid_namespace *ns); extern void free_pid(struct pid *pid); diff --git a/kernel/pid.c b/kernel/pid.c index e9fd8c132d26..4d0a9fc6e8a0 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -183,11 +183,14 @@ static int alloc_pidmap(struct pid_namespace *pid_ns) return -1; } -int next_pidmap(struct pid_namespace *pid_ns, int last) +int next_pidmap(struct pid_namespace *pid_ns, unsigned int last) { int offset; struct pidmap *map, *end; + if (last >= PID_MAX_LIMIT) + return -1; + offset = (last + 1) & BITS_PER_PAGE_MASK; map = &pid_ns->pidmap[(last + 1)/BITS_PER_PAGE]; end = &pid_ns->pidmap[PIDMAP_ENTRIES]; -- cgit v1.2.3 From 66b681ef4893e65f9219da4c1bb493dc99bde0c5 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 18 Apr 2011 10:36:54 -0700 Subject: proc: do proper range check on readdir offset commit d8bdc59f215e62098bc5b4256fd9928bf27053a1 upstream. Rather than pass in some random truncated offset to the pid-related functions, check that the offset is in range up-front. This is just cleanup, the previous commit fixed the real problem. Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/proc/base.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index acb7ef80ea4f..d073b90f5dc6 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2867,11 +2867,16 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi /* for the /proc/ directory itself, after non-process stuff has been done */ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) { - unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; - struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); + unsigned int nr; + struct task_struct *reaper; struct tgid_iter iter; struct pid_namespace *ns; + if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET) + goto out_no_task; + nr = filp->f_pos - FIRST_PROCESS_ENTRY; + + reaper = get_proc_task(filp->f_path.dentry->d_inode); if (!reaper) goto out_no_task; -- cgit v1.2.3 From 16e9999883d5aef8514a9d64f5ecec4f22634c1d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 5 Apr 2011 13:36:15 -0400 Subject: USB: EHCI: unlink unused QHs when the controller is stopped commit 94ae4976e253757e9b03a44d27d41b20f1829d80 upstream. This patch (as1458) fixes a problem affecting ultra-reliable systems: When hardware failover of an EHCI controller occurs, the data structures do not get released correctly. This is because the routine responsible for removing unused QHs from the async schedule assumes the controller is running properly (the frame counter is used in determining how long the QH has been idle) -- but when a failover causes the controller to be electronically disconnected from the PCI bus, obviously it stops running. The solution is simple: Allow scan_async() to remove a QH from the async schedule if it has been idle for long enough _or_ if the controller is stopped. Signed-off-by: Alan Stern Signed-off-by: Andi Kleen Reported-and-Tested-by: Dan Duval Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 98f022d2947f..ed8db6a23b7f 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1246,24 +1246,27 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) static void scan_async (struct ehci_hcd *ehci) { + bool stopped; struct ehci_qh *qh; enum ehci_timer_action action = TIMER_IO_WATCHDOG; ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index); timer_action_done (ehci, TIMER_ASYNC_SHRINK); rescan: + stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state); qh = ehci->async->qh_next.qh; if (likely (qh != NULL)) { do { /* clean any finished work for this qh */ - if (!list_empty (&qh->qtd_list) - && qh->stamp != ehci->stamp) { + if (!list_empty(&qh->qtd_list) && (stopped || + qh->stamp != ehci->stamp)) { int temp; /* unlinks could happen here; completion * reporting drops the lock. rescan using * the latest schedule, but don't rescan - * qhs we already finished (no looping). + * qhs we already finished (no looping) + * unless the controller is stopped. */ qh = qh_get (qh); qh->stamp = ehci->stamp; @@ -1284,9 +1287,9 @@ rescan: */ if (list_empty(&qh->qtd_list) && qh->qh_state == QH_STATE_LINKED) { - if (!ehci->reclaim - && ((ehci->stamp - qh->stamp) & 0x1fff) - >= (EHCI_SHRINK_FRAMES * 8)) + if (!ehci->reclaim && (stopped || + ((ehci->stamp - qh->stamp) & 0x1fff) + >= EHCI_SHRINK_FRAMES * 8)) start_unlink_async(ehci, qh); else action = TIMER_ASYNC_SHRINK; -- cgit v1.2.3 From b367480dbb551ca870e09dae5a28be7464dd809a Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 18 Mar 2011 21:29:01 -0700 Subject: USB: fix formatting of SuperSpeed endpoints in /proc/bus/usb/devices commit 2868a2b1ba8f9c7f6c4170519ebb6c62934df70e upstream. Isochronous and interrupt SuperSpeed endpoints use the same mechanisms for decoding bInterval values as HighSpeed ones so adjust the code accordingly. Also bandwidth reservation for SuperSpeed matches highspeed, not low/full speed. Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/core/devices.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 3449742c00e1..dcb4e5ed0a08 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -222,7 +222,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, break; case USB_ENDPOINT_XFER_INT: type = "Int."; - if (speed == USB_SPEED_HIGH) + if (speed == USB_SPEED_HIGH || speed == USB_SPEED_SUPER) interval = 1 << (desc->bInterval - 1); else interval = desc->bInterval; @@ -230,7 +230,8 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, default: /* "can't happen" */ return start; } - interval *= (speed == USB_SPEED_HIGH) ? 125 : 1000; + interval *= (speed == USB_SPEED_HIGH || + speed == USB_SPEED_SUPER) ? 125 : 1000; if (interval % 1000) unit = 'u'; else { @@ -540,8 +541,9 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, if (level == 0) { int max; - /* high speed reserves 80%, full/low reserves 90% */ - if (usbdev->speed == USB_SPEED_HIGH) + /* super/high speed reserves 80%, full/low reserves 90% */ + if (usbdev->speed == USB_SPEED_HIGH || + usbdev->speed == USB_SPEED_SUPER) max = 800; else max = FRAME_TIME_MAX_USECS_ALLOC; -- cgit v1.2.3 From 7582e0dedb0f71907b0cd6cc298b246628ced943 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 20 Mar 2011 02:15:17 -0700 Subject: USB: xhci - fix unsafe macro definitions commit 5a6c2f3ff039154872ce597952f8b8900ea0d732 upstream. Macro arguments used in expressions need to be enclosed in parenthesis to avoid unpleasant surprises. This should be queued for kernels back to 2.6.31 Signed-off-by: Dmitry Torokhov Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/xhci.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 5edb706f6f17..a6982c3bbbfc 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -232,7 +232,7 @@ struct xhci_op_regs { * notification type that matches a bit set in this bit field. */ #define DEV_NOTE_MASK (0xffff) -#define ENABLE_DEV_NOTE(x) (1 << x) +#define ENABLE_DEV_NOTE(x) (1 << (x)) /* Most of the device notification types should only be used for debug. * SW does need to pay attention to function wake notifications. */ @@ -598,11 +598,11 @@ struct xhci_ep_ctx { #define EP_STATE_STOPPED 3 #define EP_STATE_ERROR 4 /* Mult - Max number of burtst within an interval, in EP companion desc. */ -#define EP_MULT(p) ((p & 0x3) << 8) +#define EP_MULT(p) (((p) & 0x3) << 8) /* bits 10:14 are Max Primary Streams */ /* bit 15 is Linear Stream Array */ /* Interval - period between requests to an endpoint - 125u increments. */ -#define EP_INTERVAL(p) ((p & 0xff) << 16) +#define EP_INTERVAL(p) (((p) & 0xff) << 16) #define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff)) #define EP_MAXPSTREAMS_MASK (0x1f << 10) #define EP_MAXPSTREAMS(p) (((p) << 10) & EP_MAXPSTREAMS_MASK) -- cgit v1.2.3 From eaf0c653ec6898c65aceff17469a35ce97bab8aa Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 23 Mar 2011 22:41:23 -0700 Subject: USB: xhci - fix math in xhci_get_endpoint_interval() commit dfa49c4ad120a784ef1ff0717168aa79f55a483a upstream. When parsing exponent-expressed intervals we subtract 1 from the value and then expect it to match with original + 1, which is highly unlikely, and we end with frequent spew: usb 3-4: ep 0x83 - rounding interval to 512 microframes Also, parsing interval for fullspeed isochronous endpoints was incorrect - according to USB spec they use exponent-based intervals (but xHCI spec claims frame-based intervals). I trust USB spec more, especially since USB core agrees with it. This should be queued for stable kernels back to 2.6.31. Reviewed-by: Micah Elizabeth Scott Signed-off-by: Dmitry Torokhov Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/xhci-mem.c | 83 +++++++++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 25 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 8b89e0a6391d..7ddb69f3038f 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -961,6 +961,47 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud return 0; } +/* + * Convert interval expressed as 2^(bInterval - 1) == interval into + * straight exponent value 2^n == interval. + * + */ +static unsigned int xhci_parse_exponent_interval(struct usb_device *udev, + struct usb_host_endpoint *ep) +{ + unsigned int interval; + + interval = clamp_val(ep->desc.bInterval, 1, 16) - 1; + if (interval != ep->desc.bInterval - 1) + dev_warn(&udev->dev, + "ep %#x - rounding interval to %d microframes\n", + ep->desc.bEndpointAddress, + 1 << interval); + + return interval; +} + +/* + * Convert bInterval expressed in frames (in 1-255 range) to exponent of + * microframes, rounded down to nearest power of 2. + */ +static unsigned int xhci_parse_frame_interval(struct usb_device *udev, + struct usb_host_endpoint *ep) +{ + unsigned int interval; + + interval = fls(8 * ep->desc.bInterval) - 1; + interval = clamp_val(interval, 3, 10); + if ((1 << interval) != 8 * ep->desc.bInterval) + dev_warn(&udev->dev, + "ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n", + ep->desc.bEndpointAddress, + 1 << interval, + 8 * ep->desc.bInterval); + + return interval; +} + /* Return the polling or NAK interval. * * The polling interval is expressed in "microframes". If xHCI's Interval field @@ -978,43 +1019,35 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev, case USB_SPEED_HIGH: /* Max NAK rate */ if (usb_endpoint_xfer_control(&ep->desc) || - usb_endpoint_xfer_bulk(&ep->desc)) + usb_endpoint_xfer_bulk(&ep->desc)) { interval = ep->desc.bInterval; + break; + } /* Fall through - SS and HS isoc/int have same decoding */ case USB_SPEED_SUPER: if (usb_endpoint_xfer_int(&ep->desc) || - usb_endpoint_xfer_isoc(&ep->desc)) { - if (ep->desc.bInterval == 0) - interval = 0; - else - interval = ep->desc.bInterval - 1; - if (interval > 15) - interval = 15; - if (interval != ep->desc.bInterval + 1) - dev_warn(&udev->dev, "ep %#x - rounding interval to %d microframes\n", - ep->desc.bEndpointAddress, 1 << interval); + usb_endpoint_xfer_isoc(&ep->desc)) { + interval = xhci_parse_exponent_interval(udev, ep); } break; /* Convert bInterval (in 1-255 frames) to microframes and round down to * nearest power of 2. */ case USB_SPEED_FULL: + if (usb_endpoint_xfer_int(&ep->desc)) { + interval = xhci_parse_exponent_interval(udev, ep); + break; + } + /* + * Fall through for isochronous endpoint interval decoding + * since it uses the same rules as low speed interrupt + * endpoints. + */ case USB_SPEED_LOW: if (usb_endpoint_xfer_int(&ep->desc) || - usb_endpoint_xfer_isoc(&ep->desc)) { - interval = fls(8*ep->desc.bInterval) - 1; - if (interval > 10) - interval = 10; - if (interval < 3) - interval = 3; - if ((1 << interval) != 8*ep->desc.bInterval) - dev_warn(&udev->dev, - "ep %#x - rounding interval" - " to %d microframes, " - "ep desc says %d microframes\n", - ep->desc.bEndpointAddress, - 1 << interval, - 8*ep->desc.bInterval); + usb_endpoint_xfer_isoc(&ep->desc)) { + + interval = xhci_parse_frame_interval(udev, ep); } break; default: -- cgit v1.2.3 From 07991dfa5079fe9170b4285ad8fbb51781dcb22c Mon Sep 17 00:00:00 2001 From: Hans Rosenfeld Date: Wed, 18 Aug 2010 16:19:50 +0200 Subject: x86, cpu: Fix regression in AMD errata checking code commit 07a7795ca2e6e66d00b184efb46bd0e23d90d3fe upstream. A bug in the family-model-stepping matching code caused the presence of errata to go undetected when OSVW was not used. This causes hangs on some K8 systems because the E400 workaround is not enabled. Signed-off-by: Hans Rosenfeld Signed-off-by: Andi Kleen LKML-Reference: <1282141190-930137-1-git-send-email-hans.rosenfeld@amd.com> Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/amd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index f98bb34916a9..b203d0dbfc04 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -687,7 +687,7 @@ bool cpu_has_amd_erratum(const int *erratum) } /* OSVW unavailable or ID unknown, match family-model-stepping range */ - ms = (cpu->x86_model << 8) | cpu->x86_mask; + ms = (cpu->x86_model << 4) | cpu->x86_mask; while ((range = *erratum++)) if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) && (ms >= AMD_MODEL_RANGE_START(range)) && -- cgit v1.2.3 From 4aa96ce73e0282f556fdc5850313a4d0ca15532f Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 12 Jan 2011 00:34:49 -0800 Subject: net: ax25: fix information leak to userland harder commit 5b919f833d9d60588d026ad82d17f17e8872c7a9 upstream. Commit fe10ae53384e48c51996941b7720ee16995cbcb7 adds a memset() to clear the structure being sent back to userspace, but accidentally used the wrong size. Reported-by: Brad Spengler Signed-off-by: Kees Cook Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ax25/af_ax25.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 6e2371a493b7..763fd0bc9756 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1392,7 +1392,7 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, ax25_cb *ax25; int err = 0; - memset(fsa, 0, sizeof(fsa)); + memset(fsa, 0, sizeof(*fsa)); lock_sock(sk); ax25 = ax25_sk(sk); -- cgit v1.2.3 From dffa5ee4119483e30441071cfc7d94f74e82d1e9 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 31 Mar 2011 00:01:58 -0700 Subject: Input: synaptics - fix crash in synaptics_module_init() [ upstream commit 708748670c7c6dd5bd3b141473086e6937e72737 ] 'struct dmi_system_id' arrays must always have a terminator to keep dmi_check_system() from looking at data (and possibly crashing) it isn't supposed to look at. The issue went unnoticed until ef8313bb1a22e7d2125d9d758aa8a81f1de91d81, but was introduced about a year earlier with 7705d548cbe33f18ea7713b9a07aa11047aaeca4 (which also similarly changed lifebook.c, but the problem there got eliminated shortly afterwards). The first hunk therefore is a stable candidate back to 2.6.33, while the full change is needed only on 2.6.38. Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen Cc: stable@kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 705589dc9ac5..4009b4101664 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -712,8 +712,8 @@ static const struct dmi_system_id __initconst toshiba_dmi_table[] = { }, }, - { } #endif + { } }; void __init synaptics_module_init(void) -- cgit v1.2.3 From 0ed05379c28294629c08fa348c83965e098bbcf6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 25 Mar 2011 17:43:41 +0100 Subject: ath9k: fix a chip wakeup related crash in ath9k_start [ upstream commit f62d816fc4324afbb7cf90110c70b6a14139b225 ] When the chip is still asleep when ath9k_start is called, ath9k_hw_configpcipowersave can trigger a data bus error. Signed-off-by: Felix Fietkau Signed-off-by: Andi Kleen Cc: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 82cfe0f28be6..2b8c6e8884a0 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1124,6 +1124,8 @@ static int ath9k_start(struct ieee80211_hw *hw) "Starting driver with initial channel: %d MHz\n", curchan->center_freq); + ath9k_ps_wakeup(sc); + mutex_lock(&sc->mutex); if (ath9k_wiphy_started(sc)) { @@ -1238,6 +1240,8 @@ static int ath9k_start(struct ieee80211_hw *hw) mutex_unlock: mutex_unlock(&sc->mutex); + ath9k_ps_restore(sc); + return r; } -- cgit v1.2.3 From 6af5fb1038b725d5a064c003f78f855d412728df Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Wed, 6 Apr 2011 20:40:31 +0200 Subject: ath: add missing regdomain pair 0x5c mapping commit bd39a274fb7b43374c797bafdb7f506598f36f77 upstream. Joe Culler reported a problem with his AR9170 device: > ath: EEPROM regdomain: 0x5c > ath: EEPROM indicates we should expect a direct regpair map > ath: invalid regulatory domain/country code 0x5c > ath: Invalid EEPROM contents It turned out that the regdomain 'APL7_FCCA' was not mapped yet. According to Luis R. Rodriguez [Atheros' engineer] APL7 maps to FCC_CTL and FCCA maps to FCC_CTL as well, so the attached patch should be correct. Reported-by: Joe Culler Acked-by: Luis R. Rodriguez Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/ath/regd_common.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h index 248c670fdfbe..5c2cfe694152 100644 --- a/drivers/net/wireless/ath/regd_common.h +++ b/drivers/net/wireless/ath/regd_common.h @@ -195,6 +195,7 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = { {APL9_WORLD, CTL_ETSI, CTL_ETSI}, {APL3_FCCA, CTL_FCC, CTL_FCC}, + {APL7_FCCA, CTL_FCC, CTL_FCC}, {APL1_ETSIC, CTL_FCC, CTL_ETSI}, {APL2_ETSIC, CTL_FCC, CTL_ETSI}, {APL2_APLD, CTL_FCC, NO_CTL}, -- cgit v1.2.3 From 0dc54b12b37bb287ec4ef606ed3cc346b818e682 Mon Sep 17 00:00:00 2001 From: Liu Yuan Date: Tue, 19 Apr 2011 13:47:58 +0200 Subject: block, blk-sysfs: Fix an err return path in blk_register_queue() commit ed5302d3c25006a9edc7a7fbea97a30483f89ef7 upstream. We do not call blk_trace_remove_sysfs() in err return path if kobject_add() fails. This path fixes it. Signed-off-by: Liu Yuan Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- block/blk-sysfs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index d2466540488c..3eede79ad352 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -502,8 +502,10 @@ int blk_register_queue(struct gendisk *disk) return ret; ret = kobject_add(&q->kobj, kobject_get(&dev->kobj), "%s", "queue"); - if (ret < 0) + if (ret < 0) { + blk_trace_remove_sysfs(dev); return ret; + } kobject_uevent(&q->kobj, KOBJ_ADD); -- cgit v1.2.3 From 63201d75a4b0e92609642888aecc3b3dfc2e25d2 Mon Sep 17 00:00:00 2001 From: Jason Conti Date: Thu, 7 Apr 2011 21:09:57 +0200 Subject: p54: Initialize extra_len in p54_tx_80211 commit a6756da9eace8b4af73e9dea43f1fc2889224c94 upstream. This patch fixes a very serious off-by-one bug in the driver, which could leave the device in an unresponsive state. The problem was that the extra_len variable [used to reserve extra scratch buffer space for the firmware] was left uninitialized. Because p54_assign_address later needs the value to reserve additional space, the resulting frame could be to big for the small device's memory window and everything would immediately come to a grinding halt. Reference: https://bugs.launchpad.net/bugs/722185 Acked-by: Christian Lamparter Signed-off-by: Jason Conti Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/p54/txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 9ad0f5f0c884..7ef1e610d28e 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -702,7 +702,7 @@ int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb) struct p54_tx_info *p54info; struct p54_hdr *hdr; struct p54_tx_data *txhdr; - unsigned int padding, len, extra_len; + unsigned int padding, len, extra_len = 0; int i, j, ridx; u16 hdr_flags = 0, aid = 0; u8 rate, queue = 0, crypt_offset = 0; -- cgit v1.2.3 From be57626a0d05b26e7e2db01ebe3fe0c0d3e8bc2e Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 18 Apr 2011 15:45:46 +0200 Subject: x86, gart: Make sure GART does not map physmem above 1TB commit 665d3e2af83c8fbd149534db8f57d82fa6fa6753 upstream. The GART can only map physical memory below 1TB. Make sure the gart driver in the kernel does not try to map memory above 1TB. Signed-off-by: Joerg Roedel Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/1303134346-5805-5-git-send-email-joerg.roedel@amd.com Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/pci-gart_64.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 0f7f130caa67..870e069863a4 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -80,6 +80,9 @@ static u32 gart_unmapped_entry; #define AGPEXTERN #endif +/* GART can only remap to physical addresses < 1TB */ +#define GART_MAX_PHYS_ADDR (1ULL << 40) + /* backdoor interface to AGP driver */ AGPEXTERN int agp_memory_reserved; AGPEXTERN __u32 *agp_gatt_table; @@ -211,9 +214,13 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, size_t size, int dir, unsigned long align_mask) { unsigned long npages = iommu_num_pages(phys_mem, size, PAGE_SIZE); - unsigned long iommu_page = alloc_iommu(dev, npages, align_mask); + unsigned long iommu_page; int i; + if (unlikely(phys_mem + size > GART_MAX_PHYS_ADDR)) + return bad_dma_addr; + + iommu_page = alloc_iommu(dev, npages, align_mask); if (iommu_page == -1) { if (!nonforced_iommu(dev, phys_mem, size)) return phys_mem; -- cgit v1.2.3 From 8e2f9d0be8626aca810c8cac38fce207ea81af4a Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Fri, 4 Mar 2011 14:52:16 -0700 Subject: intel-iommu: Unlink domain from iommu commit a97590e56d0d58e1dd262353f7cbd84e81d8e600 upstream. When we remove a device, we unlink the iommu from the domain, but we never do the reverse unlinking of the domain from the iommu. This means that we never clear iommu->domain_ids, eventually leading to resource exhaustion if we repeatedly bind and unbind a device to a driver. Also free empty domains to avoid a resource leak. Signed-off-by: Alex Williamson Acked-by: Donald Dutile Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/pci/intel-iommu.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 8e499e8d2481..50e083e4208c 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -3260,9 +3260,15 @@ static int device_notifier(struct notifier_block *nb, if (!domain) return 0; - if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) + if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) { domain_remove_one_dev_info(domain, pdev); + if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) && + !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) && + list_empty(&domain->devices)) + domain_exit(domain); + } + return 0; } @@ -3411,6 +3417,11 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain, domain->iommu_count--; domain_update_iommu_cap(domain); spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags); + + spin_lock_irqsave(&iommu->lock, tmp_flags); + clear_bit(domain->id, iommu->domain_ids); + iommu->domains[domain->id] = NULL; + spin_unlock_irqrestore(&iommu->lock, tmp_flags); } spin_unlock_irqrestore(&device_domain_lock, flags); -- cgit v1.2.3 From e77004d6125829cc856553e08fb2d5d2afb2e289 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Fri, 4 Mar 2011 14:52:30 -0700 Subject: intel-iommu: Fix get_domain_for_dev() error path commit 2fe9723df8e45fd247782adea244a5e653c30bf4 upstream. If we run out of domain_ids and fail iommu_attach_domain(), we fall into domain_exit() without having setup enough of the domain structure for this to do anything useful. In fact, it typically runs off into the weeds walking the bogus domain->devices list. Just free the domain. Signed-off-by: Alex Williamson Acked-by: Donald Dutile Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/pci/intel-iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 50e083e4208c..83ac0a08f701 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1835,7 +1835,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) ret = iommu_attach_domain(domain, iommu); if (ret) { - domain_exit(domain); + free_domain_mem(domain); goto error; } -- cgit v1.2.3 From d287e1976eb287fbf3817df536758f1bffe74ded Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 14 Apr 2011 11:19:50 -0400 Subject: drm/radeon/kms: fix bad shift in atom iio table parser commit 8e461123f28e6b17456225e70eb834b3b30d28bb upstream. Noticed by Patrick Lowry. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/atom.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index 1d569830ed99..b913bf193dab 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -131,7 +131,7 @@ static uint32_t atom_iio_execute(struct atom_context *ctx, int base, case ATOM_IIO_MOVE_INDEX: temp &= ~((0xFFFFFFFF >> (32 - CU8(base + 1))) << - CU8(base + 2)); + CU8(base + 3)); temp |= ((index >> CU8(base + 2)) & (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base + @@ -141,7 +141,7 @@ static uint32_t atom_iio_execute(struct atom_context *ctx, int base, case ATOM_IIO_MOVE_DATA: temp &= ~((0xFFFFFFFF >> (32 - CU8(base + 1))) << - CU8(base + 2)); + CU8(base + 3)); temp |= ((data >> CU8(base + 2)) & (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base + @@ -151,7 +151,7 @@ static uint32_t atom_iio_execute(struct atom_context *ctx, int base, case ATOM_IIO_MOVE_ATTR: temp &= ~((0xFFFFFFFF >> (32 - CU8(base + 1))) << - CU8(base + 2)); + CU8(base + 3)); temp |= ((ctx-> io_attr >> CU8(base + 2)) & (0xFFFFFFFF >> (32 - -- cgit v1.2.3 From 0993450a8cccc34704e7375ca47ec555be909b05 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 25 Jan 2011 15:28:21 -0500 Subject: NFS: nfs_wcc_update_inode() should set nfsi->attr_gencount commit 27dc1cd3ad9300f81e1219e5fc305d91d85353f8 upstream. If the call to nfs_wcc_update_inode() results in an attribute update, we need to ensure that the inode's attr_gencount gets bumped too, otherwise we are not protected against races with other GETATTR calls. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfs/inode.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 099b3518feea..0cafbdb522c5 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -811,9 +811,10 @@ out: return ret; } -static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) +static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) { struct nfs_inode *nfsi = NFS_I(inode); + unsigned long ret = 0; if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE) && (fattr->valid & NFS_ATTR_FATTR_CHANGE) @@ -821,25 +822,32 @@ static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) nfsi->change_attr = fattr->change_attr; if (S_ISDIR(inode->i_mode)) nfsi->cache_validity |= NFS_INO_INVALID_DATA; + ret |= NFS_INO_INVALID_ATTR; } /* If we have atomic WCC data, we may update some attributes */ if ((fattr->valid & NFS_ATTR_FATTR_PRECTIME) && (fattr->valid & NFS_ATTR_FATTR_CTIME) - && timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) - memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); + && timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) { + memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); + ret |= NFS_INO_INVALID_ATTR; + } if ((fattr->valid & NFS_ATTR_FATTR_PREMTIME) && (fattr->valid & NFS_ATTR_FATTR_MTIME) && timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { - memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); - if (S_ISDIR(inode->i_mode)) - nfsi->cache_validity |= NFS_INO_INVALID_DATA; + memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); + if (S_ISDIR(inode->i_mode)) + nfsi->cache_validity |= NFS_INO_INVALID_DATA; + ret |= NFS_INO_INVALID_ATTR; } if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE) && (fattr->valid & NFS_ATTR_FATTR_SIZE) && i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size) - && nfsi->npages == 0) - i_size_write(inode, nfs_size_to_loff_t(fattr->size)); + && nfsi->npages == 0) { + i_size_write(inode, nfs_size_to_loff_t(fattr->size)); + ret |= NFS_INO_INVALID_ATTR; + } + return ret; } /** @@ -1153,7 +1161,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | NFS_INO_REVAL_PAGECACHE); /* Do atomic weak cache consistency updates */ - nfs_wcc_update_inode(inode, fattr); + invalid |= nfs_wcc_update_inode(inode, fattr); /* More cache consistency checks */ if (fattr->valid & NFS_ATTR_FATTR_CHANGE) { -- cgit v1.2.3 From 617a954d482ca5c165da9ec8345a02a23fbaab78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 11 Apr 2011 10:59:09 +0200 Subject: serial/imx: read cts state only after acking cts change irq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 5680e94148a86e8c31fdc5cb0ea0d5c6810c05b0 upstream. If cts changes between reading the level at the cts input (USR1_RTSS) and acking the irq (USR1_RTSD) the last edge doesn't generate an irq and uart_handle_cts_change is called with a outdated value for cts. The race was introduced by commit ceca629 ([ARM] 2971/1: i.MX uart handle rts irq) Reported-by: Arwed Springer Tested-by: Arwed Springer Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/serial/imx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index eacb588a9345..6d2028e996ad 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -383,12 +383,13 @@ static void imx_start_tx(struct uart_port *port) static irqreturn_t imx_rtsint(int irq, void *dev_id) { struct imx_port *sport = dev_id; - unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS; + unsigned int val; unsigned long flags; spin_lock_irqsave(&sport->port.lock, flags); writel(USR1_RTSD, sport->port.membase + USR1); + val = readl(sport->port.membase + USR1) & USR1_RTSS; uart_handle_cts_change(&sport->port, !!val); wake_up_interruptible(&sport->port.state->port.delta_msr_wait); -- cgit v1.2.3 From 16c67021be095358fe47d5015d9d925a723288bd Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 8 Apr 2011 16:32:16 +0900 Subject: ASoC: Fix output PGA enabling in wm_hubs CODECs commit 39cca168bdfaef9d0c496ec27f292445d6184946 upstream. The output PGA was not being powered up in headphone and speaker paths, removing the ability to offer volume control and mute with the output PGA. Signed-off-by: Mark Brown Acked-by: Liam Girdwood Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/soc/codecs/wm_hubs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 20ffd28abcd9..5093a767a72d 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -705,12 +705,12 @@ static const struct snd_soc_dapm_route analogue_routes[] = { { "SPKL", "Input Switch", "MIXINL" }, { "SPKL", "IN1LP Switch", "IN1LP" }, - { "SPKL", "Output Switch", "Left Output Mixer" }, + { "SPKL", "Output Switch", "Left Output PGA" }, { "SPKL", NULL, "TOCLK" }, { "SPKR", "Input Switch", "MIXINR" }, { "SPKR", "IN1RP Switch", "IN1RP" }, - { "SPKR", "Output Switch", "Right Output Mixer" }, + { "SPKR", "Output Switch", "Right Output PGA" }, { "SPKR", NULL, "TOCLK" }, { "SPKL Boost", "Direct Voice Switch", "Direct Voice" }, @@ -732,8 +732,8 @@ static const struct snd_soc_dapm_route analogue_routes[] = { { "SPKOUTRP", NULL, "SPKR Driver" }, { "SPKOUTRN", NULL, "SPKR Driver" }, - { "Left Headphone Mux", "Mixer", "Left Output Mixer" }, - { "Right Headphone Mux", "Mixer", "Right Output Mixer" }, + { "Left Headphone Mux", "Mixer", "Left Output PGA" }, + { "Right Headphone Mux", "Mixer", "Right Output PGA" }, { "Headphone PGA", NULL, "Left Headphone Mux" }, { "Headphone PGA", NULL, "Right Headphone Mux" }, -- cgit v1.2.3 From 4a8031feb7c4bdad402763dfee193565c99b07e8 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 23 Apr 2011 18:42:56 +0100 Subject: kconfig: Avoid buffer underrun in choice input commit 3ba41621156681afcdbcd624e3191cbc65eb94f4 upstream. Commit 40aee729b350 ('kconfig: fix default value for choice input') fixed some cases where kconfig would select the wrong option from a choice with a single valid option and thus enter an infinite loop. However, this broke the test for user input of the form 'N?', because when kconfig selects the single valid option the input is zero-length and the test will read the byte before the input buffer. If this happens to contain '?' (as it will in a mips build on Debian unstable today) then kconfig again enters an infinite loop. Signed-off-by: Ben Hutchings Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- scripts/kconfig/conf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 9960d1c303f8..7f97e3f69e80 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -330,7 +330,7 @@ static int conf_choice(struct menu *menu) } if (!child) continue; - if (line[strlen(line) - 1] == '?') { + if (line[0] && line[strlen(line) - 1] == '?') { print_help(child); continue; } -- cgit v1.2.3 From f24ac96f1acc55d78f79a3286d1ba60dbf6cbc26 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 21 Apr 2011 14:49:55 +0300 Subject: UBIFS: fix master node recovery commit 6e0d9fd38b750d678bf9fd07db23582f52fafa55 upstream. This patch fixes the following symptoms: 1. Unmount UBIFS cleanly. 2. Start mounting UBIFS R/W and have a power cut immediately 3. Start mounting UBIFS R/O, this succeeds 4. Try to re-mount UBIFS R/W - this fails immediately or later on, because UBIFS will write the master node to the flash area which has been written before. The analysis of the problem: 1. UBIFS is unmounted cleanly, both copies of the master node are clean. 2. UBIFS is being mounter R/W, starts changing master node copy 1, and a power cut happens. The copy N1 becomes corrupted. 3. UBIFS is being mounted R/O. It notices the copy N1 is corrupted and reads copy N2. Copy N2 is clean. 4. Because of R/O mode, UBIFS cannot recover copy 1. 5. The mount code (ubifs_mount()) sees that the master node is clean, so it decides that no recovery is needed. 6. We are re-mounting R/W. UBIFS believes no recovery is needed and starts updating the master node, but copy N1 is still corrupted and was not recovered! Fix this problem by marking the master node as dirty every time we recover it and we are in R/O mode. This forces further recovery and the UBIFS cleans-up the corruptions and recovers the copy N1 when re-mounting R/W later. Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ubifs/recovery.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 109c6ea03bb5..b712ed6fb6c4 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c @@ -300,6 +300,32 @@ int ubifs_recover_master_node(struct ubifs_info *c) goto out_free; } memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ); + + /* + * We had to recover the master node, which means there was an + * unclean reboot. However, it is possible that the master node + * is clean at this point, i.e., %UBIFS_MST_DIRTY is not set. + * E.g., consider the following chain of events: + * + * 1. UBIFS was cleanly unmounted, so the master node is clean + * 2. UBIFS is being mounted R/W and starts changing the master + * node in the first (%UBIFS_MST_LNUM). A power cut happens, + * so this LEB ends up with some amount of garbage at the + * end. + * 3. UBIFS is being mounted R/O. We reach this place and + * recover the master node from the second LEB + * (%UBIFS_MST_LNUM + 1). But we cannot update the media + * because we are being mounted R/O. We have to defer the + * operation. + * 4. However, this master node (@c->mst_node) is marked as + * clean (since the step 1). And if we just return, the + * mount code will be confused and won't recover the master + * node when it is re-mounter R/W later. + * + * Thus, to force the recovery by marking the master node as + * dirty. + */ + c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); } else { /* Write the recovered master node */ c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1; -- cgit v1.2.3 From 7821dc28348d2634d67b8cf2da72308101d1bdfd Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Tue, 16 Nov 2010 19:41:36 -0800 Subject: Remove extra struct page member from the buffer info structure commit b1d670f10e8078485884f0cf7e384d890909aeaa upstream. declaration. Reported-by: Andi Kleen Signed-off-by: Greg Rose Signed-off-by: Andi Kleen Tested-by: Emil Tantilov Signed-off-by: Jeff Kirsher Cc: Andreas Radke Signed-off-by: Greg Kroah-Hartman --- drivers/net/igbvf/igbvf.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/igbvf/igbvf.h b/drivers/net/igbvf/igbvf.h index debeee2dc717..f7ae2846bf16 100644 --- a/drivers/net/igbvf/igbvf.h +++ b/drivers/net/igbvf/igbvf.h @@ -126,7 +126,6 @@ struct igbvf_buffer { unsigned int page_offset; }; }; - struct page *page; }; union igbvf_desc { -- cgit v1.2.3 From 7d7fcb84736f7be2552c796047b69fb0dc46ea75 Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Thu, 17 Feb 2011 13:13:55 +0100 Subject: dasd: correct device table commit 5da24b7627ff821e154a3aaecd5d60e1d8e228a5 upstream. The 3880 storage control unit supports a 3380 device type, but not a 3390 device type. Reported-by: Stephen Powell Signed-off-by: Stefan Haberland Signed-off-by: Martin Schwidefsky Signed-off-by: Andi Kleen Cc: Stephen Powell Cc: Jonathan Nieder Cc: Bastian Blank --- drivers/s390/block/dasd_eckd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index ab84da5592e8..06f249ba9dca 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -63,7 +63,7 @@ static struct dasd_discipline dasd_eckd_discipline; static struct ccw_device_id dasd_eckd_ids[] = { { CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3390, 0), .driver_info = 0x1}, { CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3390, 0), .driver_info = 0x2}, - { CCW_DEVICE_DEVTYPE (0x3880, 0, 0x3390, 0), .driver_info = 0x3}, + { CCW_DEVICE_DEVTYPE (0x3880, 0, 0x3380, 0), .driver_info = 0x3}, { CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3380, 0), .driver_info = 0x4}, { CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3380, 0), .driver_info = 0x5}, { CCW_DEVICE_DEVTYPE (0x9343, 0, 0x9345, 0), .driver_info = 0x6}, -- cgit v1.2.3 From 2e0220abd543b17359395e2ab9fdda3a5223988e Mon Sep 17 00:00:00 2001 From: "Fry, Donald H" Date: Wed, 16 Feb 2011 11:49:34 -0800 Subject: iwlagn: Support new 5000 microcode. commit 41504cce240f791f1e16561db95728c5537fbad9 upstream. New iwlwifi-5000 microcode requires driver support for API version 5. Signed-off-by: Don Fry Signed-off-by: Wey-Yi Guy Signed-off-by: Stanislaw Gruszka Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index a28af7eb67eb..0a67558ac0e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -51,7 +51,7 @@ #include "iwl-agn-debugfs.h" /* Highest firmware API version supported */ -#define IWL5000_UCODE_API_MAX 2 +#define IWL5000_UCODE_API_MAX 5 #define IWL5150_UCODE_API_MAX 2 /* Lowest firmware API version supported */ -- cgit v1.2.3 From 78823deddd26e3e59ed15dee48520c03897030e2 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 23 Feb 2011 11:19:17 -0300 Subject: uvcvideo: Fix descriptor parsing for video output devices commit 4093a5c4a3f59cba1a085bbf87b6ffdddc5a443d upstream. Commit 4057ac6ca9a77c4275b34b5925ab5c99557913b1 V4L/DVB (13505): uvcvideo: Refactor chain scan broke output terminals parsing. Fix it. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/media/video/uvc/uvc_driver.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 838b56f097cf..e24f9133bdaa 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -1261,6 +1261,14 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, break; + case UVC_OTT_VENDOR_SPECIFIC: + case UVC_OTT_DISPLAY: + case UVC_OTT_MEDIA_TRANSPORT_OUTPUT: + if (uvc_trace_param & UVC_TRACE_PROBE) + printk(" OT %d", entity->id); + + break; + case UVC_TT_STREAMING: if (UVC_ENTITY_IS_ITERM(entity)) { if (uvc_trace_param & UVC_TRACE_PROBE) -- cgit v1.2.3 From 971f304b0ecef95693e5c46fb534366d0fef94cc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 23 Mar 2011 15:50:39 -0700 Subject: Revert "intel_idle: PCI quirk to prevent Lenovo Ideapad s10-3 boot hang" This reverts commit 05f7676dc3559c2b9061fda4e44c085a8d32fb05. To quote Len Brown: intel_idle was deemed a "feature", and thus not included in 2.6.33.stable, and thus 2.6.33.stable does not need this patch. so I'm removing it. Cc: Len Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/pci/quirks.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 9cd70007d936..06b234f09233 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -149,26 +149,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_1, quirk_isa_d DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_dma_hangs); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs); -/* - * Intel NM10 "TigerPoint" LPC PM1a_STS.BM_STS must be clear - * for some HT machines to use C4 w/o hanging. - */ -static void __devinit quirk_tigerpoint_bm_sts(struct pci_dev *dev) -{ - u32 pmbase; - u16 pm1a; - - pci_read_config_dword(dev, 0x40, &pmbase); - pmbase = pmbase & 0xff80; - pm1a = inw(pmbase); - - if (pm1a & 0x10) { - dev_info(&dev->dev, FW_BUG "TigerPoint LPC.BM_STS cleared\n"); - outw(0x10, pmbase); - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGP_LPC, quirk_tigerpoint_bm_sts); - /* * Chipsets where PCI->PCI transfers vanish or hang */ -- cgit v1.2.3 From 1171ee52d9bc2940298844b6f485686d75fab25f Mon Sep 17 00:00:00 2001 From: Lydia Wang Date: Tue, 22 Mar 2011 16:23:23 +0800 Subject: ALSA: hda - VIA: Add missing support for VT1718S in A-A path commit ab657e0cacc39d88145871c6a3c844597c02d406 upstream. Modify mute_aa_path() function to support VT1718S codec. Signed-off-by: Lydia Wang Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_via.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 73453814e098..4a749a9dda15 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -1300,6 +1300,11 @@ static void mute_aa_path(struct hda_codec *codec, int mute) start_idx = 2; end_idx = 4; break; + case VT1718S: + nid_mixer = 0x21; + start_idx = 1; + end_idx = 3; + break; default: return; } -- cgit v1.2.3 From 98081a1026dd80b985a084df2678e7d032729f6d Mon Sep 17 00:00:00 2001 From: Lydia Wang Date: Tue, 22 Mar 2011 16:21:38 +0800 Subject: ALSA: hda - VIA: Fix stereo mixer recording no sound issue commit bff5fbf50bd498c217994bd2d41a53ac3141185a upstream. Modify function via_mux_enum_put() to fix stereo mixer recording no sound issue. Signed-off-by: Lydia Wang Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_via.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 4a749a9dda15..92387d6d8767 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -1091,6 +1091,7 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol, struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + int ret; if (!spec->mux_nids[adc_idx]) return -EINVAL; @@ -1099,12 +1100,14 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol, AC_VERB_GET_POWER_STATE, 0x00) != AC_PWRST_D0) snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0, AC_VERB_SET_POWER_STATE, AC_PWRST_D0); - /* update jack power state */ - set_jack_power_state(codec); - return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, + ret = snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); + /* update jack power state */ + set_jack_power_state(codec); + + return ret; } static int via_independent_hp_info(struct snd_kcontrol *kcontrol, -- cgit v1.2.3 From f0aa357c5f66cc5befc35d5d438d323182cdeb2a Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 20 Apr 2011 15:57:14 +0200 Subject: iwlwifi: fix skb usage after free [AK: Did some changes for the backport to .35. Stanislaw, please verify them] Since commit a120e912eb51e347f36c71b60a1d13af74d30e83 Author: Stanislaw Gruszka Date: Fri Feb 19 15:47:33 2010 -0800 iwlwifi: sanity check before counting number of tfds can be free we use skb->data after calling ieee80211_tx_status_irqsafe(), which could free skb instantly. On current kernels I do not observe practical problems related with bug, but on 2.6.35.y it cause random system hangs when stressing wireless link. Cc: stable@kernel.org # 2.6.32+ Signed-off-by: Stanislaw Gruszka Signed-off-by: Andi Kleen --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 3a3d27c20c42..cf64575067e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -1141,11 +1141,14 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { tx_info = &txq->txb[txq->q.read_ptr]; - iwlagn_tx_status(priv, tx_info->skb[0]); + + if (WARN_ON_ONCE(tx_info->skb[0] == NULL)) + continue; hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; - if (hdr && ieee80211_is_data_qos(hdr->frame_control)) + if (ieee80211_is_data_qos(hdr->frame_control)) nfreed++; + iwlagn_tx_status(priv, tx_info->skb[0]); tx_info->skb[0] = NULL; if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) -- cgit v1.2.3 From 62e2d392a18f2a3149e31fecbe18a32a06587174 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 2 Nov 2010 08:05:51 +0100 Subject: intel-iommu: Fix use after release during device attach upstream commit 7a6610139a Obtain the new pgd pointer before releasing the page containing this value. Cc: stable@kernel.org Signed-off-by: Jan Kiszka Signed-off-by: Andi Kleen Reviewed-by: Sheng Yang Signed-off-by: David Woodhouse --- drivers/pci/intel-iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 83ac0a08f701..46fcc591d5ed 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -3638,9 +3638,9 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, pte = dmar_domain->pgd; if (dma_pte_present(pte)) { - free_pgtable_page(dmar_domain->pgd); dmar_domain->pgd = (struct dma_pte *) phys_to_virt(dma_pte_addr(pte)); + free_pgtable_page(pte); } dmar_domain->agaw--; } -- cgit v1.2.3 From e6d11da6869184f5cd3375a2b636e1aae9898a8f Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Sep 2010 00:57:32 -0400 Subject: USB: Fix unplug of device with active streams upstream commit: b214f191d95ba4b5a35aebd69cd129cf7e3b1884 If I unplug a device while the UAS driver is loaded, I get an oops in usb_free_streams(). This is because usb_unbind_interface() calls usb_disable_interface() which calls usb_disable_endpoint() which sets ep_out and ep_in to NULL. Then the UAS driver calls usb_pipe_endpoint() which returns a NULL pointer and passes an array of NULL pointers to usb_free_streams(). I think the correct fix for this is to check for the NULL pointer in usb_free_streams() rather than making the driver check for this situation. My original patch for this checked for dev->state == USB_STATE_NOTATTACHED, but the call to usb_disable_interface() is conditional, so not all drivers would want this check. Note from Sarah Sharp: This patch does avoid a potential dereference, but the real fix (which will be implemented later) is to set the .soft_unbind flag in the usb_driver structure for the UAS driver, and all drivers that allocate streams. The driver should free any streams when it is unbound from the interface. This avoids leaking stream rings in the xHCI driver when usb_disable_interface() is called. This should be queued for stable trees back to 2.6.35. Signed-off-by: Matthew Wilcox Signed-off-by: Sarah Sharp Signed-off-by: Andi Kleen Cc: stable@kernel.org --- drivers/usb/core/hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 12742f152f43..7d0c7a68a9fd 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1874,7 +1874,7 @@ void usb_free_streams(struct usb_interface *interface, /* Streams only apply to bulk endpoints. */ for (i = 0; i < num_eps; i++) - if (!usb_endpoint_xfer_bulk(&eps[i]->desc)) + if (!eps[i] || !usb_endpoint_xfer_bulk(&eps[i]->desc)) return; hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags); -- cgit v1.2.3 From a6cba0b73761e2d3b94b0cceb15ee1f5f52d2b85 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 12 Apr 2011 23:06:28 -0700 Subject: USB: xhci - also free streams when resetting devices upstream commit: 2dea75d96ade3c7cd2bfe73f99c7b3291dc3d03a Currently, when resetting a device, xHCI driver disables all but one endpoints and frees their rings, but leaves alone any streams that might have been allocated. Later, when users try to free allocated streams, we oops in xhci_setup_no_streams_ep_input_ctx() because ep->ring is NULL. Let's free not only rings but also stream data as well, so that calling free_streams() on a device that was reset will be safe. This should be queued for stable trees back to 2.6.35. Reviewed-by: Micah Elizabeth Scott Signed-off-by: Dmitry Torokhov Signed-off-by: Sarah Sharp Signed-off-by: Andi Kleen Cc: stable@kernel.org --- drivers/usb/host/xhci.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 2ff4f6383da6..807f8e2366ac 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2010,10 +2010,18 @@ int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev) /* Everything but endpoint 0 is disabled, so free or cache the rings. */ last_freed_endpoint = 1; for (i = 1; i < 31; ++i) { - if (!virt_dev->eps[i].ring) - continue; - xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i); - last_freed_endpoint = i; + struct xhci_virt_ep *ep = &virt_dev->eps[i]; + + if (ep->ep_state & EP_HAS_STREAMS) { + xhci_free_stream_info(xhci, ep->stream_info); + ep->stream_info = NULL; + ep->ep_state &= ~EP_HAS_STREAMS; + } + + if (ep->ring) { + xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i); + last_freed_endpoint = i; + } } xhci_dbg(xhci, "Output context after successful reset device cmd:\n"); xhci_dbg_ctx(xhci, virt_dev->out_ctx, last_freed_endpoint); -- cgit v1.2.3 From 9128ce02d90d51012f561526d8c052f85a0d725b Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Thu, 14 Apr 2011 16:11:35 +0100 Subject: 2.6.35.y: Revert "SH: Add missing consts to sys_execve() declaration" This reverts commit 1219932ca26da2026e598590a3b7a2f36b3c3621 (commit d8b5fc01683c66060edc202d6bb5635365822181 upstream). The reverted commit depends on an upstream commit that has not been applied to 2.6.35.y (d7627467b7a8dd6944885290a03a07ceb28c10eb). This fixes a build failure on all SH devices: /arch/sh/kernel/process_32.c:299: error: conflicting types for 'sys_execve' /arch/sh/include/asm/syscalls_32.h:22: note: previous declaration of 'sys_execve' was here Signed-off-by: Phil Edworthy Signed-off-by: Andi Kleen --- arch/sh/include/asm/syscalls_32.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sh/include/asm/syscalls_32.h b/arch/sh/include/asm/syscalls_32.h index 611e92d90475..8b30200305c3 100644 --- a/arch/sh/include/asm/syscalls_32.h +++ b/arch/sh/include/asm/syscalls_32.h @@ -19,8 +19,8 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs __regs); -asmlinkage int sys_execve(char __user *ufilename, const char __user * __user *uargv, - const char __user * __user *uenvp, unsigned long r7, +asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv, + char __user * __user *uenvp, unsigned long r7, struct pt_regs __regs); asmlinkage int sys_sigsuspend(old_sigset_t mask, unsigned long r5, unsigned long r6, unsigned long r7, -- cgit v1.2.3 From a37486058b79610f79fabe9dba4156de0493f24c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 1 Mar 2011 13:23:27 -0800 Subject: Revert "TPM: Long default timeout fix" [ upstream commit 8d1dc20e8d689c7e6a0a4d2c94e36a99d5793ecb ] This reverts commit c4ff4b829ef9e6353c0b133b7adb564a68054979. Ted Ts'o reports: "TPM is working for me so I can log into employer's network in 2.6.37. It broke when I tried 2.6.38-rc6, with the following relevant lines from my dmesg: [ 11.081627] tpm_tis 00:0b: 1.2 TPM (device-id 0x0, rev-id 78) [ 25.734114] tpm_tis 00:0b: Operation Timed out [ 78.040949] tpm_tis 00:0b: Operation Timed out This caused me to get suspicious, especially since the _other_ TPM commit in 2.6.38 had already been reverted, so I tried reverting commit c4ff4b829e: "TPM: Long default timeout fix". With this commit reverted, my TPM on my Lenovo T410 is once again working." Requested-and-tested-by: Theodore Ts'o Acked-by: Rajiv Andrade Signed-off-by: Linus Torvalds Signed-off-by: Andi Kleen --- drivers/char/tpm/tpm.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 12c089863e59..b14b240103b0 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -354,14 +354,12 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, tpm_protected_ordinal_duration[ordinal & TPM_PROTECTED_ORDINAL_MASK]; - if (duration_idx != TPM_UNDEFINED) { + if (duration_idx != TPM_UNDEFINED) duration = chip->vendor.duration[duration_idx]; - /* if duration is 0, it's because chip->vendor.duration wasn't */ - /* filled yet, so we set the lowest timeout just to give enough */ - /* time for tpm_get_timeouts() to succeed */ - return (duration <= 0 ? HZ : duration); - } else + if (duration <= 0) return 2 * 60 * HZ; + else + return duration; } EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); -- cgit v1.2.3 From f60b63aaa8f2054b5c8bac192ba99e3a99f2d72f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 20 Feb 2011 10:03:12 -0800 Subject: Revert "tpm_tis: Use timeouts returned from TPM" [ upstream commit e58713724059da7d2982d6ad945192c8fca5b729 ] This reverts commit 9b29050f8f75916f974a2d231ae5d3cd59792296. It has caused hibernate regressions, for example Juri Sladby's report: "I'm unable to hibernate 2.6.37.1 unless I rmmod tpm_tis: [10974.074587] Suspending console(s) (use no_console_suspend to debug) [10974.103073] tpm_tis 00:0c: Operation Timed out [10974.103089] legacy_suspend(): pnp_bus_suspend+0x0/0xa0 returns -62 [10974.103095] PM: Device 00:0c failed to freeze: error -62" and Rafael points out that some of the new conditionals in that commit seem to make no sense. This commit needs more work and testing, let's revert it for now. Reported-by: Norbert Preining Reported-and-requested-by: Jiri Slaby Cc: Stefan Berger Cc: Guillaume Chazarain Cc: Rajiv Andrade Acked-by: Rafael J. Wysocki Signed-off-by: Linus Torvalds Signed-off-by: Andi Kleen --- drivers/char/tpm/tpm.c | 18 ++---------------- drivers/char/tpm/tpm.h | 2 -- drivers/char/tpm/tpm_tis.c | 4 +--- 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index b14b240103b0..2df6c26bbf57 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -565,11 +565,9 @@ duration: if (rc) return; - if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || - be32_to_cpu(tpm_cmd.header.out.length) - != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32)) + if (be32_to_cpu(tpm_cmd.header.out.return_code) + != 3 * sizeof(u32)) return; - duration_cap = &tpm_cmd.params.getcap_out.cap.duration; chip->vendor.duration[TPM_SHORT] = usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short)); @@ -913,18 +911,6 @@ ssize_t tpm_show_caps_1_2(struct device * dev, } EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); -ssize_t tpm_show_timeouts(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct tpm_chip *chip = dev_get_drvdata(dev); - - return sprintf(buf, "%d %d %d\n", - jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]), - jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]), - jiffies_to_usecs(chip->vendor.duration[TPM_LONG])); -} -EXPORT_SYMBOL_GPL(tpm_show_timeouts); - ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index ba1779c2cffd..792868d24f2a 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -56,8 +56,6 @@ extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr, char *); extern ssize_t tpm_show_temp_deactivated(struct device *, struct device_attribute *attr, char *); -extern ssize_t tpm_show_timeouts(struct device *, - struct device_attribute *attr, char *); struct tpm_chip; diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index ef9c4acf88e4..1030f8420137 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -355,7 +355,6 @@ static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL); static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); -static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL); static struct attribute *tis_attrs[] = { &dev_attr_pubek.attr, @@ -365,8 +364,7 @@ static struct attribute *tis_attrs[] = { &dev_attr_owned.attr, &dev_attr_temp_deactivated.attr, &dev_attr_caps.attr, - &dev_attr_cancel.attr, - &dev_attr_timeouts.attr, NULL, + &dev_attr_cancel.attr, NULL, }; static struct attribute_group tis_attr_grp = { -- cgit v1.2.3 From 47764cfbd17b4796f7f2d90c13832313ea95343f Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Tue, 26 Apr 2011 20:21:50 -0400 Subject: 2.6.35.13 longterm review Also please revert the patch "fix-cred-leak-in-af_netlink" from 2.6.35.12. The proper fix was "af_netlink-add-needed-scm_destroy-after-scm_send" which was also added in that release. Here's a revert patch: Signed-off-by: Andi Kleen --- net/netlink/af_netlink.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index eb1647873261..eea6817fa9fd 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1333,16 +1333,12 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, return err; if (msg->msg_namelen) { - if (addr->nl_family != AF_NETLINK) { - err = -EINVAL; - goto out; - } + if (addr->nl_family != AF_NETLINK) + return -EINVAL; dst_pid = addr->nl_pid; dst_group = ffs(addr->nl_groups); - if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND)) { - err = -EPERM; - goto out; - } + if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND)) + return -EPERM; } else { dst_pid = nlk->dst_pid; dst_group = nlk->dst_group; @@ -1394,8 +1390,6 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT); out: - scm_destroy(siocb->scm); - siocb->scm = NULL; return err; } -- cgit v1.2.3 From 4de01ac37194505a91082dc9e131c5fe32b7b527 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 28 Apr 2011 08:21:24 -0700 Subject: release-2.6.35.13 Release 2.6.35.13 From: Andi Kleen Release 2.6.35.13 Signed-off-by: Andi Kleen --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 92b2538892af..5ade8188d821 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 35 -EXTRAVERSION = .12 +EXTRAVERSION = .13 NAME = Yokohama # *DOCUMENTATION* -- cgit v1.2.3 From d247496cd6a6a936cee3e1b1a28ea5139515e156 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 21 Apr 2011 17:28:13 -0400 Subject: kbuild: Disable -Wunused-but-set-variable for gcc 4.6.0 [ upstream commit af0e5d565d2fffcd97d1e2d89669d627cc04e8b8 ] Disable the new -Wunused-but-set-variable that was added in gcc 4.6.0 It produces more false positives than useful warnings. This can still be enabled using W=1 [AK: dropped W=1 support in backport] Signed-off-by: Dave Jones Acked-by: Sam Ravnborg Tested-by: Sam Ravnborg Signed-off-by: Michal Marek Signed-off-by: Andi Kleen --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 5ade8188d821..1d483a728225 100644 --- a/Makefile +++ b/Makefile @@ -546,6 +546,9 @@ ifndef CONFIG_CC_STACKPROTECTOR KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector) endif +# This warning generated too much noise in a regular build. +KBUILD_CFLAGS += $(call cc-option, -Wno-unused-but-set-variable) + ifdef CONFIG_FRAME_POINTER KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls else -- cgit v1.2.3 From eaea8f19f079912b532fc85a3182f134f962b1f2 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Mon, 2 May 2011 12:51:15 +0200 Subject: kbuild: Fix passing -Wno-* options to gcc 4.4+ [ upstream commit 8417da6f2128008c431c7d130af6cd3d9079922e ] Starting with 4.4, gcc will happily accept -Wno- in the cc-option test and complain later when compiling a file that has some other warning. This rather unexpected behavior is intentional as per http://gcc.gnu.org/PR28322, so work around it by testing for support of the opposite option (without the no-). Introduce a new Makefile function cc-disable-warning that does this and update two uses of cc-option in the toplevel Makefile. Reported-and-tested-by: Stephen Rothwell Signed-off-by: Michal Marek Signed-off-by: Andi Kleen --- Documentation/kbuild/makefiles.txt | 12 ++++++++++++ Makefile | 4 ++-- scripts/Kbuild.include | 5 +++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index 71c602d61680..ab8689b94d65 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -502,6 +502,18 @@ more details, with real examples. gcc >= 3.00. For gcc < 3.00, -malign-functions=4 is used. Note: cc-option-align uses KBUILD_CFLAGS for $(CC) options + cc-disable-warning + cc-disable-warning checks if gcc supports a given warning and returns + the commandline switch to disable it. This special function is needed, + because gcc 4.4 and later accept any unknown -Wno-* option and only + warn about it if there is another warning in the source file. + + Example: + KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable) + + In the above example, -Wno-unused-but-set-variable will be added to + KBUILD_CFLAGS only if gcc really accepts it. + cc-version cc-version returns a numerical version of the $(CC) compiler version. The format is where both are two digits. So for example diff --git a/Makefile b/Makefile index 1d483a728225..a3d866b2e81e 100644 --- a/Makefile +++ b/Makefile @@ -547,7 +547,7 @@ KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector) endif # This warning generated too much noise in a regular build. -KBUILD_CFLAGS += $(call cc-option, -Wno-unused-but-set-variable) +KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable) ifdef CONFIG_FRAME_POINTER KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls @@ -577,7 +577,7 @@ CHECKFLAGS += $(NOSTDINC_FLAGS) KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) # disable pointer signed / unsigned warnings in gcc 4.0 -KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,) +KBUILD_CFLAGS += $(call cc-disable-warning, pointer-sign) # disable invalid "can't wrap" optimizations for signed / pointers KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow) diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index ed2773edfe71..ba25c440f9f6 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -118,6 +118,11 @@ cc-option-yn = $(call try-run,\ cc-option-align = $(subst -functions=0,,\ $(call cc-option,-falign-functions=0,-malign-functions=0)) +# cc-disable-warning +# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable) +cc-disable-warning = $(call try-run,\ + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -xc /dev/null -o "$$TMP",-Wno-$(strip $(1))) + # cc-version # Usage gcc-ver := $(call cc-version) cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC)) -- cgit v1.2.3 From 27752f2920dcbaae3a13a3caac8db94d9a9e427a Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 1 Aug 2011 13:54:41 -0700 Subject: maintainer Add Andi Kleen as 2.6.35 longterm maintainer From: Andi Kleen People complained about me not being in the MAINTAINERS file. So fix that. Signed-off-by: Andi Kleen --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 696e7d216bb6..d0cdb2f944da 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3444,6 +3444,12 @@ F: drivers/lguest/ F: include/linux/lguest*.h F: arch/x86/include/asm/lguest*.h +LINUX 2.6.35 LONGTERM: +M: Andi Kleen +L: stable@kernel.org +S: Maintained +F: * + LINUX FOR IBM pSERIES (RS/6000) M: Paul Mackerras W: http://www.ibm.com/linux/ltc/projects/ppc -- cgit v1.2.3 From 399f9eb9c628914fe5f1acef5bb2dd736227597c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 08:27:05 -0300 Subject: Remove the old V4L1 v4lgrab.c file [ upstream commit 55fe25b418640fad04190103274841b2c907bacd ] This example file uses the old V4L1 API. It also doesn't use libv4l. So, it is completely obsolete. A good example already exists at v4l-utils (v4l2grab.c): http://git.linuxtv.org/v4l-utils.git [AK: included in 2.6.35 because v4lgrab doesn't build without the host's linux/videodev.h] Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andi Kleen --- Documentation/Makefile | 2 +- Documentation/video4linux/Makefile | 8 -- Documentation/video4linux/v4lgrab.c | 201 ------------------------------------ 3 files changed, 1 insertion(+), 210 deletions(-) delete mode 100644 Documentation/video4linux/Makefile delete mode 100644 Documentation/video4linux/v4lgrab.c diff --git a/Documentation/Makefile b/Documentation/Makefile index 6fc7ea1d1f9d..9b4bc5c76f33 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -1,3 +1,3 @@ obj-m := DocBook/ accounting/ auxdisplay/ connector/ \ filesystems/ filesystems/configfs/ ia64/ laptops/ networking/ \ - pcmcia/ spi/ timers/ video4linux/ vm/ watchdog/src/ + pcmcia/ spi/ timers/ vm/ watchdog/src/ diff --git a/Documentation/video4linux/Makefile b/Documentation/video4linux/Makefile deleted file mode 100644 index 1ed0e98d057d..000000000000 --- a/Documentation/video4linux/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# kbuild trick to avoid linker error. Can be omitted if a module is built. -obj- := dummy.o - -# List of programs to build -hostprogs-y := v4lgrab - -# Tell kbuild to always build the programs -always := $(hostprogs-y) diff --git a/Documentation/video4linux/v4lgrab.c b/Documentation/video4linux/v4lgrab.c deleted file mode 100644 index c8ded175796e..000000000000 --- a/Documentation/video4linux/v4lgrab.c +++ /dev/null @@ -1,201 +0,0 @@ -/* Simple Video4Linux image grabber. */ -/* - * Video4Linux Driver Test/Example Framegrabbing Program - * - * Compile with: - * gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab - * Use as: - * v4lgrab >image.ppm - * - * Copyright (C) 1998-05-03, Phil Blundell - * Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c - * with minor modifications (Dave Forrest, drf5n@virginia.edu). - * - * - * For some cameras you may need to pre-load libv4l to perform - * the necessary decompression, e.g.: - * - * export LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so - * ./v4lgrab >image.ppm - * - * see http://hansdegoede.livejournal.com/3636.html for details. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define VIDEO_DEV "/dev/video0" - -/* Stole this from tvset.c */ - -#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b) \ -{ \ - switch (format) \ - { \ - case VIDEO_PALETTE_GREY: \ - switch (depth) \ - { \ - case 4: \ - case 6: \ - case 8: \ - (r) = (g) = (b) = (*buf++ << 8);\ - break; \ - \ - case 16: \ - (r) = (g) = (b) = \ - *((unsigned short *) buf); \ - buf += 2; \ - break; \ - } \ - break; \ - \ - \ - case VIDEO_PALETTE_RGB565: \ - { \ - unsigned short tmp = *(unsigned short *)buf; \ - (r) = tmp&0xF800; \ - (g) = (tmp<<5)&0xFC00; \ - (b) = (tmp<<11)&0xF800; \ - buf += 2; \ - } \ - break; \ - \ - case VIDEO_PALETTE_RGB555: \ - (r) = (buf[0]&0xF8)<<8; \ - (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8; \ - (b) = ((buf[1] << 2 ) & 0xF8)<<8; \ - buf += 2; \ - break; \ - \ - case VIDEO_PALETTE_RGB24: \ - (r) = buf[0] << 8; (g) = buf[1] << 8; \ - (b) = buf[2] << 8; \ - buf += 3; \ - break; \ - \ - default: \ - fprintf(stderr, \ - "Format %d not yet supported\n", \ - format); \ - } \ -} - -static int get_brightness_adj(unsigned char *image, long size, int *brightness) { - long i, tot = 0; - for (i=0;i= 126 && (tot/(size*3)) <= 130); -} - -int main(int argc, char ** argv) -{ - int fd = open(VIDEO_DEV, O_RDONLY), f; - struct video_capability cap; - struct video_window win; - struct video_picture vpic; - - unsigned char *buffer, *src; - int bpp = 24, r = 0, g = 0, b = 0; - unsigned int i, src_depth = 16; - - if (fd < 0) { - perror(VIDEO_DEV); - exit(1); - } - - if (ioctl(fd, VIDIOCGCAP, &cap) < 0) { - perror("VIDIOGCAP"); - fprintf(stderr, "(" VIDEO_DEV " not a video4linux device?)\n"); - close(fd); - exit(1); - } - - if (ioctl(fd, VIDIOCGWIN, &win) < 0) { - perror("VIDIOCGWIN"); - close(fd); - exit(1); - } - - if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) { - perror("VIDIOCGPICT"); - close(fd); - exit(1); - } - - if (cap.type & VID_TYPE_MONOCHROME) { - vpic.depth=8; - vpic.palette=VIDEO_PALETTE_GREY; /* 8bit grey */ - if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { - vpic.depth=6; - if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { - vpic.depth=4; - if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { - fprintf(stderr, "Unable to find a supported capture format.\n"); - close(fd); - exit(1); - } - } - } - } else { - vpic.depth=24; - vpic.palette=VIDEO_PALETTE_RGB24; - - if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { - vpic.palette=VIDEO_PALETTE_RGB565; - vpic.depth=16; - - if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { - vpic.palette=VIDEO_PALETTE_RGB555; - vpic.depth=15; - - if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { - fprintf(stderr, "Unable to find a supported capture format.\n"); - return -1; - } - } - } - } - - buffer = malloc(win.width * win.height * bpp); - if (!buffer) { - fprintf(stderr, "Out of memory.\n"); - exit(1); - } - - do { - int newbright; - read(fd, buffer, win.width * win.height * bpp); - f = get_brightness_adj(buffer, win.width * win.height, &newbright); - if (f) { - vpic.brightness += (newbright << 8); - if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { - perror("VIDIOSPICT"); - break; - } - } - } while (f); - - fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height); - - src = buffer; - - for (i = 0; i < win.width * win.height; i++) { - READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b); - fputc(r>>8, stdout); - fputc(g>>8, stdout); - fputc(b>>8, stdout); - } - - close(fd); - return 0; -} -- cgit v1.2.3 From 7f482d63e27696707ac00eb838ed9379f89957b8 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Thu, 14 Apr 2011 20:55:16 +0400 Subject: agp: fix arbitrary kernel memory writes [ upstream commit 194b3da873fd334ef183806db751473512af29ce ] pg_start is copied from userspace on AGPIOC_BIND and AGPIOC_UNBIND ioctl cmds of agp_ioctl() and passed to agpioc_bind_wrap(). As said in the comment, (pg_start + mem->page_count) may wrap in case of AGPIOC_BIND, and it is not checked at all in case of AGPIOC_UNBIND. As a result, user with sufficient privileges (usually "video" group) may generate either local DoS or privilege escalation. Signed-off-by: Vasiliy Kulikov Signed-off-by: Dave Airlie Signed-off-by: Andi Kleen --- drivers/char/agp/generic.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index d2abf5143983..7858016c1119 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -1122,8 +1122,8 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type) return -EINVAL; } - /* AK: could wrap */ - if ((pg_start + mem->page_count) > num_entries) + if (((pg_start + mem->page_count) > num_entries) || + ((pg_start + mem->page_count) < pg_start)) return -EINVAL; j = pg_start; @@ -1157,7 +1157,7 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type) { size_t i; struct agp_bridge_data *bridge; - int mask_type; + int mask_type, num_entries; bridge = mem->bridge; if (!bridge) @@ -1169,6 +1169,11 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type) if (type != mem->type) return -EINVAL; + num_entries = agp_num_entries(); + if (((pg_start + mem->page_count) > num_entries) || + ((pg_start + mem->page_count) < pg_start)) + return -EINVAL; + mask_type = bridge->driver->agp_type_to_mask_type(bridge, type); if (mask_type != 0) { /* The generic routines know nothing of memory types */ -- cgit v1.2.3 From ce8b71ac8d2d454629ba04bd64bfd1a2fbe1d06c Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Thu, 14 Apr 2011 20:55:19 +0400 Subject: agp: fix OOM and buffer overflow [ upstream commit b522f02184b413955f3bc952e3776ce41edc6355 ] page_count is copied from userspace. agp_allocate_memory() tries to check whether this number is too big, but doesn't take into account the wrap case. Also agp_create_user_memory() doesn't check whether alloc_size is calculated from num_agp_pages variable without overflow. This may lead to allocation of too small buffer with following buffer overflow. Another problem in agp code is not addressed in the patch - kernel memory exhaustion (AGPIOC_RESERVE and AGPIOC_ALLOCATE ioctls). It is not checked whether requested pid is a pid of the caller (no check in agpioc_reserve_wrap()). Each allocation is limited to 16KB, though, there is no per-process limit. This might lead to OOM situation, which is not even solved in case of the caller death by OOM killer - the memory is allocated for another (faked) process. Signed-off-by: Vasiliy Kulikov Signed-off-by: Dave Airlie Signed-off-by: Andi Kleen --- drivers/char/agp/generic.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 7858016c1119..8df122af0f1a 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -122,6 +122,9 @@ static struct agp_memory *agp_create_user_memory(unsigned long num_agp_pages) struct agp_memory *new; unsigned long alloc_size = num_agp_pages*sizeof(struct page *); + if (INT_MAX/sizeof(struct page *) < num_agp_pages) + return NULL; + new = kzalloc(sizeof(struct agp_memory), GFP_KERNEL); if (new == NULL) return NULL; @@ -241,11 +244,14 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge, int scratch_pages; struct agp_memory *new; size_t i; + int cur_memory; if (!bridge) return NULL; - if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp) + cur_memory = atomic_read(&bridge->current_memory_agp); + if ((cur_memory + page_count > bridge->max_memory_agp) || + (cur_memory + page_count < page_count)) return NULL; if (type >= AGP_USER_TYPES) { -- cgit v1.2.3 From e58c04b185972bebd832a9716a037aa1c5fab745 Mon Sep 17 00:00:00 2001 From: Jim Bos Date: Sat, 13 Nov 2010 12:13:53 +0100 Subject: i8k: Tell gcc that *regs gets clobbered [ upstream commit 6b4e81db2552bad04100e7d5ddeed7e848f53b48 ] More recent GCC caused the i8k driver to stop working, on Slackware compiler was upgraded from gcc-4.4.4 to gcc-4.5.1 after which it didn't work anymore, meaning the driver didn't load or gave total nonsensical output. As it turned out the asm(..) statement forgot to mention it modifies the *regs variable. Credits to Andi Kleen and Andreas Schwab for providing the fix. Signed-off-by: Jim Bos Cc: Andi Kleen Cc: Andreas Schwab Signed-off-by: Linus Torvalds Signed-off-by: Andi Kleen --- drivers/char/i8k.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index 4cd8b227c11f..0add4a667e93 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c @@ -141,7 +141,7 @@ static int i8k_smm(struct smm_regs *regs) "lahf\n\t" "shrl $8,%%eax\n\t" "andl $1,%%eax\n" - :"=a"(rc) + :"=a"(rc), "+m" (*regs) : "a"(regs) : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"); #else @@ -166,7 +166,8 @@ static int i8k_smm(struct smm_regs *regs) "movl %%edx,0(%%eax)\n\t" "lahf\n\t" "shrl $8,%%eax\n\t" - "andl $1,%%eax\n":"=a"(rc) + "andl $1,%%eax\n" + :"=a"(rc), "+m" (*regs) : "a"(regs) : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"); #endif -- cgit v1.2.3 From f6f0a6fc894aad0108952e957d4e79241d4c6cab Mon Sep 17 00:00:00 2001 From: Jim Bos Date: Mon, 15 Nov 2010 21:22:37 +0100 Subject: Fix gcc 4.5.1 miscompiling drivers/char/i8k.c (again) [ upstream commit 22d3243de86bc92d874abb7c5b185d5c47aba323 ] The fix in commit 6b4e81db2552 ("i8k: Tell gcc that *regs gets clobbered") to work around the gcc miscompiling i8k.c to add "+m (*regs)" caused register pressure problems and a build failure. Changing the 'asm' statement to 'asm volatile' instead should prevent that and works around the gcc bug as well, so we can remove the "+m". [ Background on the gcc bug: a memory clobber fails to mark the function the asm resides in as non-pure (aka "__attribute__((const))"), so if the function does nothing else that triggers the non-pure logic, gcc will think that that function has no side effects at all. As a result, callers will be mis-compiled. Adding the "+m" made gcc see that it's not a pure function, and so does "asm volatile". The problem was never really the need to mark "*regs" as changed, since the memory clobber did that part - the problem was just a bug in the gcc "pure" function analysis - Linus ] Signed-off-by: Jim Bos Acked-by: Jakub Jelinek Cc: Andi Kleen Cc: Andreas Schwab Signed-off-by: Linus Torvalds Signed-off-by: Andi Kleen --- drivers/char/i8k.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index 0add4a667e93..0bd4364fa39d 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c @@ -119,7 +119,7 @@ static int i8k_smm(struct smm_regs *regs) int eax = regs->eax; #if defined(CONFIG_X86_64) - asm("pushq %%rax\n\t" + asm volatile("pushq %%rax\n\t" "movl 0(%%rax),%%edx\n\t" "pushq %%rdx\n\t" "movl 4(%%rax),%%ebx\n\t" @@ -141,11 +141,11 @@ static int i8k_smm(struct smm_regs *regs) "lahf\n\t" "shrl $8,%%eax\n\t" "andl $1,%%eax\n" - :"=a"(rc), "+m" (*regs) + :"=a"(rc) : "a"(regs) : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"); #else - asm("pushl %%eax\n\t" + asm volatile("pushl %%eax\n\t" "movl 0(%%eax),%%edx\n\t" "push %%edx\n\t" "movl 4(%%eax),%%ebx\n\t" @@ -167,7 +167,7 @@ static int i8k_smm(struct smm_regs *regs) "lahf\n\t" "shrl $8,%%eax\n\t" "andl $1,%%eax\n" - :"=a"(rc), "+m" (*regs) + :"=a"(rc) : "a"(regs) : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"); #endif -- cgit v1.2.3 From 057192c2e12ff9a7d7f168913025106cf6ccbd8c Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 15 Feb 2011 15:55:07 +0100 Subject: USB: serial/usb_wwan, fix tty NULL dereference [ upstream commit 38237fd2be9421c104f84cc35665097bdce89013 ] tty_port_tty_get may return without any problems NULL. Handle this case and do not oops in usb_wwan_indat_callback by dereferencing it. The oops: Unable to handle kernel paging request for data at address 0x000000d8 Faulting instruction address: 0xc0175b3c Oops: Kernel access of bad area, sig: 11 [#1] PowerPC 40x Platform last sysfs file: /sys/devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:09.2/usb1/idVendor Modules linked in: NIP: c0175b3c LR: c0175e7c CTR: c0215c90 REGS: c77f7d50 TRAP: 0300 Not tainted (2.6.37-rc5) MSR: 00021030 CR: 88482028 XER: 2000005f DEAR: 000000d8, ESR: 00000000 TASK = c7141b90[1149] 'wvdial' THREAD: c2750000 GPR00: 00021030 c77f7e00 c7141b90 00000000 0000000e 00000000 0000000e c0410680 GPR08: c683db00 00000000 00000001 c03c81f8 88482028 10073ef4 ffffffb9 ffffff94 GPR16: 00000000 fde036c0 00200200 00100100 00000001 ffffff8d c34fabcc 00000000 GPR24: c71120d4 00000000 00000000 0000000e 00021030 00000000 00000000 0000000e NIP [c0175b3c] tty_buffer_request_room+0x2c/0x194 LR [c0175e7c] tty_insert_flip_string_fixed_flag+0x3c/0xb0 Call Trace: [c77f7e00] [00000003] 0x3 (unreliable) [c77f7e30] [c0175e7c] tty_insert_flip_string_fixed_flag+0x3c/0xb0 [c77f7e60] [c0215df4] usb_wwan_indat_callback+0x164/0x170 ... References: https://bugzilla.kernel.org/show_bug.cgi?id=24582 Cc: Amit Shah Cc: baoyb Signed-off-by: Jiri Slaby Cc: stable Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/usb_wwan.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 0c70b4a621bb..964a58e68c18 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -216,12 +216,15 @@ static void usb_wwan_indat_callback(struct urb *urb) __func__, status, endpoint); } else { tty = tty_port_tty_get(&port->port); - if (urb->actual_length) { - tty_insert_flip_string(tty, data, urb->actual_length); - tty_flip_buffer_push(tty); - } else - dbg("%s: empty read urb received", __func__); - tty_kref_put(tty); + if (tty) { + if (urb->actual_length) { + tty_insert_flip_string(tty, data, + urb->actual_length); + tty_flip_buffer_push(tty); + } else + dbg("%s: empty read urb received", __func__); + tty_kref_put(tty); + } /* Resubmit urb so we continue receiving */ if (status != -ESHUTDOWN) { -- cgit v1.2.3 From fff22ebf8262a288e4541d69fd959d9f2d8e4cc7 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 3 Sep 2010 02:59:14 +0000 Subject: ipv6: add special mode accept_ra=2 to accept RA while configured as router [ upstream commit 65e9b62d4503849b10bedfc29bff0473760cc597 ] The current IPv6 behavior is to not accept router advertisements while forwarding, i.e. configured as router. This does make sense, a router is typically not supposed to be auto configured. However there are exceptions and we should allow the current behavior to be overwritten. Therefore this patch enables the user to overrule the "if forwarding enabled then don't listen to RAs" rule by setting accept_ra to the special value of 2. An alternative would be to ignore the forwarding switch alltogether and solely accept RAs based on the value of accept_ra. However, I found that if not intended, accepting RAs as a router can lead to strange unwanted behavior therefore we it seems wise to only do so if the user explicitely asks for this behavior. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller Signed-off-by: Andi Kleen --- net/ipv6/ndisc.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 2efef52fb461..0df797699192 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1105,6 +1105,18 @@ errout: rtnl_set_sk_err(net, RTNLGRP_ND_USEROPT, err); } +static inline int accept_ra(struct inet6_dev *in6_dev) +{ + /* + * If forwarding is enabled, RA are not accepted unless the special + * hybrid mode (accept_ra=2) is enabled. + */ + if (in6_dev->cnf.forwarding && in6_dev->cnf.accept_ra < 2) + return 0; + + return in6_dev->cnf.accept_ra; +} + static void ndisc_router_discovery(struct sk_buff *skb) { struct ra_msg *ra_msg = (struct ra_msg *)skb_transport_header(skb); @@ -1158,8 +1170,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) return; } - /* skip route and link configuration on routers */ - if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) + if (!accept_ra(in6_dev)) goto skip_linkparms; #ifdef CONFIG_IPV6_NDISC_NODETYPE @@ -1309,8 +1320,7 @@ skip_linkparms: NEIGH_UPDATE_F_ISROUTER); } - /* skip route and link configuration on routers */ - if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) + if (!accept_ra(in6_dev)) goto out; #ifdef CONFIG_IPV6_ROUTE_INFO -- cgit v1.2.3 From 3f14204734d5cb567edbc6e90885a5d6cae21ad0 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Tue, 5 Apr 2011 12:45:59 -0400 Subject: mpt2sas: prevent heap overflows and unchecked reads [ upstream commit a1f74ae82d133ebb2aabb19d181944b4e83e9960 ] At two points in handling device ioctls via /dev/mpt2ctl, user-supplied length values are used to copy data from userspace into heap buffers without bounds checking, allowing controllable heap corruption and subsequently privilege escalation. Additionally, user-supplied values are used to determine the size of a copy_to_user() as well as the offset into the buffer to be read, with no bounds checking, allowing users to read arbitrary kernel memory. Signed-off-by: Dan Rosenberg Cc: stable@kernel.org Acked-by: Eric Moore Signed-off-by: James Bottomley Signed-off-by: Andi Kleen --- drivers/scsi/mpt2sas/mpt2sas_ctl.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index d88e9756d8f5..9e689c874cce 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c @@ -637,6 +637,13 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, data_out_sz = karg.data_out_size; data_in_sz = karg.data_in_size; + /* Check for overflow and wraparound */ + if (karg.data_sge_offset * 4 > ioc->request_sz || + karg.data_sge_offset > (UINT_MAX / 4)) { + ret = -EINVAL; + goto out; + } + /* copy in request message frame from user */ if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) { printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__, @@ -1883,7 +1890,7 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) Mpi2DiagBufferPostReply_t *mpi_reply; int rc, i; u8 buffer_type; - unsigned long timeleft; + unsigned long timeleft, request_size, copy_size; u16 smid; u16 ioc_status; u8 issue_reset = 0; @@ -1919,6 +1926,8 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) return -ENOMEM; } + request_size = ioc->diag_buffer_sz[buffer_type]; + if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) { printk(MPT2SAS_ERR_FMT "%s: either the starting_offset " "or bytes_to_read are not 4 byte aligned\n", ioc->name, @@ -1926,13 +1935,23 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) return -EINVAL; } + if (karg.starting_offset > request_size) + return -EINVAL; + diag_data = (void *)(request_data + karg.starting_offset); dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(%p), " "offset(%d), sz(%d)\n", ioc->name, __func__, diag_data, karg.starting_offset, karg.bytes_to_read)); + /* Truncate data on requests that are too large */ + if ((diag_data + karg.bytes_to_read < diag_data) || + (diag_data + karg.bytes_to_read > request_data + request_size)) + copy_size = request_size - karg.starting_offset; + else + copy_size = karg.bytes_to_read; + if (copy_to_user((void __user *)uarg->diagnostic_data, - diag_data, karg.bytes_to_read)) { + diag_data, copy_size)) { printk(MPT2SAS_ERR_FMT "%s: Unable to write " "mpt_diag_read_buffer_t data @ %p\n", ioc->name, __func__, diag_data); -- cgit v1.2.3 From 42d14d10679e6baebdb67cc1484af8bb037bd441 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Wed, 20 Apr 2011 19:27:13 -0700 Subject: set memory ranges in N_NORMAL_MEMORY when onlined commit d9b41e0b54fd7e164daf1e9c539c1070398aa02e upstream. When a DISCONTIGMEM memory range is brought online as a NUMA node, it also needs to have its bet set in N_NORMAL_MEMORY. This is necessary for generic kernel code that utilizes N_NORMAL_MEMORY as a subset of N_ONLINE for memory savings. These types of hacks can hopefully be removed once DISCONTIGMEM is either removed or abstracted away from CONFIG_NUMA. Fixes a panic in the slub code which only initializes structures for N_NORMAL_MEMORY to save memory: Backtrace: [<000000004021c938>] add_partial+0x28/0x98 [<000000004021faa0>] __slab_free+0x1d0/0x1d8 [<000000004021fd04>] kmem_cache_free+0xc4/0x128 [<000000004033bf9c>] ida_get_new_above+0x21c/0x2c0 [<00000000402a8980>] sysfs_new_dirent+0xd0/0x238 [<00000000402a974c>] create_dir+0x5c/0x168 [<00000000402a9ab0>] sysfs_create_dir+0x98/0x128 [<000000004033d6c4>] kobject_add_internal+0x114/0x258 [<000000004033d9ac>] kobject_add_varg+0x7c/0xa0 [<000000004033df20>] kobject_add+0x50/0x90 [<000000004033dfb4>] kobject_create_and_add+0x54/0xc8 [<00000000407862a0>] cgroup_init+0x138/0x1f0 [<000000004077ce50>] start_kernel+0x5a0/0x840 [<000000004011fa3c>] start_parisc+0xa4/0xb8 [<00000000404bb034>] packet_ioctl+0x16c/0x208 [<000000004049ac30>] ip_mroute_setsockopt+0x260/0xf20 Signed-off-by: David Rientjes Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/parisc/mm/init.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index f4f4d700833a..7fd8aadd8a8e 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -266,8 +266,10 @@ static void __init setup_bootmem(void) } memset(pfnnid_map, 0xff, sizeof(pfnnid_map)); - for (i = 0; i < npmem_ranges; i++) + for (i = 0; i < npmem_ranges; i++) { + node_set_state(i, N_NORMAL_MEMORY); node_set_online(i); + } #endif /* -- cgit v1.2.3 From 42e4c1f34c0d1a2fdfb0b829ec9645daf16dcd7a Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 3 Apr 2011 12:40:24 -0300 Subject: FLEXCOP-PCI: fix __xlate_proc_name-warning for flexcop-pci commit b934c20de1398d4a82d2ecfeb588a214a910f13f upstream. This patch fixes the warning about bad names for sys-fs and other kernel-things. The flexcop-pci driver was using '/'-characters in it, which is not good. This has been fixed in several attempts by several people, but obviously never made it into the kernel. Signed-off-by: Patrick Boettcher Cc: Steffen Barszus Cc: Boris Cuber Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/media/dvb/b2c2/flexcop-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c index 227c0200b70a..4f3e3ceaa7c9 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/dvb/b2c2/flexcop-pci.c @@ -38,7 +38,7 @@ MODULE_PARM_DESC(debug, DEBSTATUS); #define DRIVER_VERSION "0.1" -#define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver" +#define DRIVER_NAME "flexcop-pci" #define DRIVER_AUTHOR "Patrick Boettcher " struct flexcop_pci { -- cgit v1.2.3 From 3703f45f5bc34dae097b135bfcd0448d73848a3c Mon Sep 17 00:00:00 2001 From: Michael Schmitz Date: Tue, 26 Apr 2011 14:51:53 +1200 Subject: m68k/mm: Set all online nodes in N_NORMAL_MEMORY commit 4aac0b4815ba592052758f4b468f253d383dc9d6 upstream. For m68k, N_NORMAL_MEMORY represents all nodes that have present memory since it does not support HIGHMEM. This patch sets the bit at the time node_present_pages has been set by free_area_init_node. At the time the node is brought online, the node state would have to be done unconditionally since information about present memory has not yet been recorded. If N_NORMAL_MEMORY is not accurate, slub may encounter errors since it uses this nodemask to setup per-cache kmem_cache_node data structures. This pach is an alternative to the one proposed by David Rientjes attempting to set node state immediately when bringing the node online. Signed-off-by: Michael Schmitz Tested-by: Thorsten Glaser Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/m68k/mm/motorola.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c index 02b7a03e4226..8b3db1c587fc 100644 --- a/arch/m68k/mm/motorola.c +++ b/arch/m68k/mm/motorola.c @@ -300,6 +300,8 @@ void __init paging_init(void) zones_size[ZONE_DMA] = m68k_memory[i].size >> PAGE_SHIFT; free_area_init_node(i, zones_size, m68k_memory[i].addr >> PAGE_SHIFT, NULL); + if (node_present_pages(i)) + node_set_state(i, N_NORMAL_MEMORY); } } -- cgit v1.2.3 From 86b7b580a603f3ecd18e3b19e5d9dc2eb7c458dc Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 27 Apr 2011 11:49:09 -0400 Subject: nfs: don't lose MS_SYNCHRONOUS on remount of noac mount commit 26c4c170731f00008f4317a2888a0a07ac99d90d upstream. On a remount, the VFS layer will clear the MS_SYNCHRONOUS bit on the assumption that the flags on the mount syscall will have it set if the remounted fs is supposed to keep it. In the case of "noac" though, MS_SYNCHRONOUS is implied. A remount of such a mount will lose the MS_SYNCHRONOUS flag since "sync" isn't part of the mount options. Reported-by: Max Matveev Signed-off-by: Jeff Layton Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfs/super.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 381d9291ea17..f9fce46a9713 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -2001,6 +2001,15 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data) if (error < 0) goto out; + /* + * noac is a special case. It implies -o sync, but that's not + * necessarily reflected in the mtab options. do_remount_sb + * will clear MS_SYNCHRONOUS if -o sync wasn't specified in the + * remount options, so we have to explicitly reset it. + */ + if (data->flags & NFS_MOUNT_NOAC) + *flags |= MS_SYNCHRONOUS; + /* compare new mount options with old ones */ error = nfs_compare_remount_data(nfss, data); out: -- cgit v1.2.3 From 67d456fdeff3f5ee21ea788b0ce1800eba0db5cb Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 15 Apr 2011 17:34:18 -0400 Subject: NFSv4.1: Ensure state manager thread dies on last umount commit 47c2199b6eb5fbe38ddb844db7cdbd914d304f9c upstream. Currently, the state manager may continue to try recovering state forever even after the last filesystem to reference that nfs_client has umounted. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfs/nfs4state.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 53f05ddce765..55bfe0e2afe8 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1410,7 +1410,7 @@ static void nfs4_state_manager(struct nfs_client *clp) int status = 0; /* Ensure exclusive access to NFSv4 state */ - for(;;) { + do { if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { /* We're going to have to re-establish a clientid */ status = nfs4_reclaim_lease(clp); @@ -1493,7 +1493,7 @@ static void nfs4_state_manager(struct nfs_client *clp) break; if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) break; - } + } while (atomic_read(&clp->cl_count) > 1); return; out_error: printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" -- cgit v1.2.3 From 5920c3712db2d05f820426fbf1123fd00e2d1e0d Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 18 Apr 2011 10:17:17 -0700 Subject: Input: xen-kbdfront - fix mouse getting stuck after save/restore commit c36b58e8a9112017c2bcc322cc98e71241814303 upstream. Mouse gets "stuck" after restore of PV guest but buttons are in working condition. If driver has been configured for ABS coordinates at start it will get XENKBD_TYPE_POS events and then suddenly after restore it'll start getting XENKBD_TYPE_MOTION events, that will be dropped later and they won't get into user-space. Regression was introduced by hunk 5 and 6 of 5ea5254aa0ad269cfbd2875c973ef25ab5b5e9db ("Input: xen-kbdfront - advertise either absolute or relative coordinates"). Driver on restore should ask xen for request-abs-pointer again if it is available. So restore parts that did it before 5ea5254. Acked-by: Olaf Hering Signed-off-by: Igor Mammedov Signed-off-by: Andi Kleen [v1: Expanded the commit description] Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Dmitry Torokhov --- drivers/input/xen-kbdfront.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c index 6ad8be171d70..477f3ecd066e 100644 --- a/drivers/input/xen-kbdfront.c +++ b/drivers/input/xen-kbdfront.c @@ -285,7 +285,7 @@ static void xenkbd_backend_changed(struct xenbus_device *dev, enum xenbus_state backend_state) { struct xenkbd_info *info = dev_get_drvdata(&dev->dev); - int val; + int ret, val; switch (backend_state) { case XenbusStateInitialising: @@ -296,6 +296,16 @@ static void xenkbd_backend_changed(struct xenbus_device *dev, case XenbusStateInitWait: InitWait: + ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend, + "feature-abs-pointer", "%d", &val); + if (ret < 0) + val = 0; + if (val) { + ret = xenbus_printf(XBT_NIL, info->xbdev->nodename, + "request-abs-pointer", "1"); + if (ret) + pr_warning("can't request abs-pointer\n"); + } xenbus_switch_state(dev, XenbusStateConnected); break; -- cgit v1.2.3 From 7d9cdcaaa0cc1e45614863d097b727519c723d81 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Tue, 5 Apr 2011 13:27:31 -0400 Subject: pmcraid: reject negative request size commit 5f6279da3760ce48f478f2856aacebe0c59a39f3 upstream. There's a code path in pmcraid that can be reached via device ioctl that causes all sorts of ugliness, including heap corruption or triggering the OOM killer due to consecutive allocation of large numbers of pages. Not especially relevant from a security perspective, since users must have CAP_SYS_ADMIN to open the character device. First, the user can call pmcraid_chr_ioctl() with a type PMCRAID_PASSTHROUGH_IOCTL. A pmcraid_passthrough_ioctl_buffer is copied in, and the request_size variable is set to buffer->ioarcb.data_transfer_length, which is an arbitrary 32-bit signed value provided by the user. If a negative value is provided here, bad things can happen. For example, pmcraid_build_passthrough_ioadls() is called with this request_size, which immediately calls pmcraid_alloc_sglist() with a negative size. The resulting math on allocating a scatter list can result in an overflow in the kzalloc() call (if num_elem is 0, the sglist will be smaller than expected), or if num_elem is unexpectedly large the subsequent loop will call alloc_pages() repeatedly, a high number of pages will be allocated and the OOM killer might be invoked. Prevent this value from being negative in pmcraid_ioctl_passthrough(). Signed-off-by: Dan Rosenberg Cc: Anil Ravindranath Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/scsi/pmcraid.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index c44e4ab4e938..06ea03d05b93 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -3528,6 +3528,9 @@ static long pmcraid_ioctl_passthrough( rc = -EFAULT; goto out_free_buffer; } + } else if (request_size < 0) { + rc = -EINVAL; + goto out_free_buffer; } /* check if we have any additional command parameters */ -- cgit v1.2.3 From 4f1ca069a7660ba29ca9bcc126539982a804b38f Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 22 Apr 2011 10:39:59 -0500 Subject: put stricter guards on queue dead checks commit 86cbfb5607d4b81b1a993ff689bbd2addd5d3a9b upstream. SCSI uses request_queue->queuedata == NULL as a signal that the queue is dying. We set this state in the sdev release function. However, this allows a small window where we release the last reference but haven't quite got to this stage yet and so something will try to take a reference in scsi_request_fn and oops. It's very rare, but we had a report here, so we're pushing this as a bug fix The actual fix is to set request_queue->queuedata to NULL in scsi_remove_device() before we drop the reference. This causes correct automatic rejects from scsi_request_fn as people who hold additional references try to submit work and prevents anything from getting a new reference to the sdev that way. Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/scsi/scsi_sysfs.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 86ea5f3e74ea..2b265a16e92f 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -319,14 +319,8 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work) kfree(evt); } - if (sdev->request_queue) { - sdev->request_queue->queuedata = NULL; - /* user context needed to free queue */ - scsi_free_queue(sdev->request_queue); - /* temporary expedient, try to catch use of queue lock - * after free of sdev */ - sdev->request_queue = NULL; - } + /* NULL queue means the device can't be used */ + sdev->request_queue = NULL; scsi_target_reap(scsi_target(sdev)); @@ -961,6 +955,12 @@ void __scsi_remove_device(struct scsi_device *sdev) if (sdev->host->hostt->slave_destroy) sdev->host->hostt->slave_destroy(sdev); transport_destroy_device(dev); + + /* cause the request function to reject all I/O requests */ + sdev->request_queue->queuedata = NULL; + + /* Freeing the queue signals to block that we're done */ + scsi_free_queue(sdev->request_queue); put_device(dev); } -- cgit v1.2.3 From 725296955c01285787cdfbaf813298626c9c09ee Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Tue, 29 Mar 2011 00:46:12 -0400 Subject: mmc: sdhci-pci: Fix error case in sdhci_pci_probe_slot() commit 9fdcdbb0d84922e7ccda2f717a04ea62629f7e18 upstream. If pci_ioremap_bar() fails during probe, we "goto release;" and free the host, but then we return 0 -- which tells sdhci_pci_probe() that the probe succeeded. Since we think the probe succeeded, when we unload sdhci we'll go to sdhci_pci_remove_slot() and it will try to dereference slot->host, which is now NULL because we freed it in the error path earlier. The patch simply sets ret appropriately, so that sdhci_pci_probe() will detect the failure immediately and bail out. Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/mmc/host/sdhci-pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 65483fdea45b..657809aff2e4 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -653,6 +653,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( host->ioaddr = pci_ioremap_bar(pdev, bar); if (!host->ioaddr) { dev_err(&pdev->dev, "failed to remap registers\n"); + ret = -ENOMEM; goto release; } -- cgit v1.2.3 From 5c8e95fea6c5c922ecdfde9d41f460dcc2e797e4 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 27 Apr 2011 14:24:19 +0100 Subject: mmc: sdhci: Check mrq->cmd in sdhci_tasklet_finish commit b7b4d3426d2b5ecab21578eb20d8e456a1aace8f upstream. It seems that under certain circumstances that the sdhci_tasklet_finish() call can be entered with mrq->cmd set to NULL, causing the system to crash with a NULL pointer de-reference. Unable to handle kernel NULL pointer dereference at virtual address 00000000 PC is at sdhci_tasklet_finish+0x34/0xe8 LR is at sdhci_tasklet_finish+0x24/0xe8 Seen on S3C6410 system. Signed-off-by: Ben Dooks Signed-off-by: Mark Brown Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/mmc/host/sdhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index c6d1bd8d4ac4..0f5a5a2c93dc 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1289,7 +1289,7 @@ static void sdhci_tasklet_finish(unsigned long param) * upon error conditions. */ if (!(host->flags & SDHCI_DEVICE_DEAD) && - (mrq->cmd->error || + ((mrq->cmd && mrq->cmd->error) || (mrq->data && (mrq->data->error || (mrq->data->stop && mrq->data->stop->error))) || (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) { -- cgit v1.2.3 From 882041535c8d3244c46bcca0f2109ac514e74dd5 Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Wed, 27 Apr 2011 17:35:31 -0400 Subject: mmc: sdhci: Check mrq != NULL in sdhci_tasklet_finish commit 0c9c99a765321104cc5f9c97f949382a9ba4927e upstream. It seems that under certain circumstances the sdhci_tasklet_finish() call can be entered with mrq set to NULL, causing the system to crash with a NULL pointer de-reference. Seen on S3C6410 system. Based on a patch by Dimitris Papastamos. Reported-by: Dimitris Papastamos Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/mmc/host/sdhci.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 0f5a5a2c93dc..182504c95ce9 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1278,6 +1278,13 @@ static void sdhci_tasklet_finish(unsigned long param) host = (struct sdhci_host*)param; + /* + * If this tasklet gets rescheduled while running, it will + * be run again afterwards but without any active request. + */ + if (!host->mrq) + return; + spin_lock_irqsave(&host->lock, flags); del_timer(&host->timer); -- cgit v1.2.3 From d282c26a7de21ea3b4df913be7a89035553ed846 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 2 May 2011 14:21:44 -0400 Subject: USB: fix regression in usbip by setting has_tt flag commit cee6a262550f53a13acfefbc1e3e5ff35c96182c upstream. This patch (as1460) fixes a regression in the usbip driver caused by the new check for Transaction Translators in USB-2 hubs. The root hub registered by vhci_hcd needs to have the has_tt flag set, because it can connect to low- and full-speed devices as well as high-speed devices. Signed-off-by: Alan Stern Signed-off-by: Andi Kleen Reported-and-tested-by: Nikola Ciprich Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/vhci_hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index e003bebd8fa5..b509a5dc286c 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -1135,7 +1135,7 @@ static int vhci_hcd_probe(struct platform_device *pdev) usbip_uerr("create hcd failed\n"); return -ENOMEM; } - + hcd->has_tt = 1; /* this is private data for vhci_hcd */ the_controller = hcd_to_vhci(hcd); -- cgit v1.2.3 From 00b450cca3cfa0495203f171e787d5c629cbaeac Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Fri, 29 Apr 2011 15:48:07 +0100 Subject: ARM: 6891/1: prevent heap corruption in OABI semtimedop commit 0f22072ab50cac7983f9660d33974b45184da4f9 upstream. When CONFIG_OABI_COMPAT is set, the wrapper for semtimedop does not bound the nsops argument. A sufficiently large value will cause an integer overflow in allocation size, followed by copying too much data into the allocated buffer. Fix this by restricting nsops to SEMOPM. Untested. Signed-off-by: Dan Rosenberg Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/arm/kernel/sys_oabi-compat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c index 33ff678e32f2..73bb15cf7e32 100644 --- a/arch/arm/kernel/sys_oabi-compat.c +++ b/arch/arm/kernel/sys_oabi-compat.c @@ -311,7 +311,7 @@ asmlinkage long sys_oabi_semtimedop(int semid, long err; int i; - if (nsops < 1) + if (nsops < 1 || nsops > SEMOPM) return -EINVAL; sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL); if (!sops) -- cgit v1.2.3 From 18c76472ce00748c2d53ff46f3a70537b632f304 Mon Sep 17 00:00:00 2001 From: Sachin Prabhu Date: Wed, 20 Apr 2011 13:09:35 +0100 Subject: Open with O_CREAT flag set fails to open existing files on non writable directories commit 1574dff8996ab1ed92c09012f8038b5566fce313 upstream. An open on a NFS4 share using the O_CREAT flag on an existing file for which we have permissions to open but contained in a directory with no write permissions will fail with EACCES. A tcpdump shows that the client had set the open mode to UNCHECKED which indicates that the file should be created if it doesn't exist and encountering an existing flag is not an error. Since in this case the file exists and can be opened by the user, the NFS server is wrong in attempting to check create permissions on the parent directory. The patch adds a conditional statement to check for create permissions only if the file doesn't exist. Signed-off-by: Sachin S. Prabhu Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfsd/vfs.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 40962779c666..a57c453ddfd6 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1386,7 +1386,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, goto out; if (!(iap->ia_valid & ATTR_MODE)) iap->ia_mode = 0; - err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); + err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC); if (err) goto out; @@ -1408,6 +1408,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, if (IS_ERR(dchild)) goto out_nfserr; + /* If file doesn't exist, check for permissions to create one */ + if (!dchild->d_inode) { + err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); + if (err) + goto out; + } + err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); if (err) goto out; -- cgit v1.2.3 From 25b405bacb846370a9af427662594eabfb72803b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 19 Apr 2011 20:36:59 -0700 Subject: can: Add missing socket check in can/bcm release. commit c6914a6f261aca0c9f715f883a353ae7ff51fe83 upstream. We can get here with a NULL socket argument passed from userspace, so we need to handle it accordingly. Signed-off-by: Dave Jones Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/can/bcm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/can/bcm.c b/net/can/bcm.c index 9d5e8accfab1..56d20a29a7e9 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -1424,9 +1424,14 @@ static int bcm_init(struct sock *sk) static int bcm_release(struct socket *sock) { struct sock *sk = sock->sk; - struct bcm_sock *bo = bcm_sk(sk); + struct bcm_sock *bo; struct bcm_op *op, *next; + if (sk == NULL) + return 0; + + bo = bcm_sk(sk); + /* remove bcm_ops, timer, rx_unregister(), etc. */ unregister_netdevice_notifier(&bo->notifier); -- cgit v1.2.3 From fa2d122182a496f3e43aaa595ed972341beff80a Mon Sep 17 00:00:00 2001 From: Timo Warns Date: Thu, 14 Apr 2011 15:21:56 -0700 Subject: fs/partitions/ldm.c: fix oops caused by corrupted partition table commit c340b1d640001c8c9ecff74f68fd90422ae2448a upstream. The kernel automatically evaluates partition tables of storage devices. The code for evaluating LDM partitions (in fs/partitions/ldm.c) contains a bug that causes a kernel oops on certain corrupted LDM partitions. A kernel subsystem seems to crash, because, after the oops, the kernel no longer recognizes newly connected storage devices. The patch validates the value of vblk_size. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Timo Warns Cc: Eugene Teo Cc: Harvey Harrison Cc: Richard Russon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/partitions/ldm.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c index 5638c19a0450..9fea43ba9fa6 100644 --- a/fs/partitions/ldm.c +++ b/fs/partitions/ldm.c @@ -1299,6 +1299,11 @@ static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags) BUG_ON (!data || !frags); + if (size < 2 * VBLK_SIZE_HEAD) { + ldm_error("Value of size is to small."); + return false; + } + group = get_unaligned_be32(data + 0x08); rec = get_unaligned_be16(data + 0x0C); num = get_unaligned_be16(data + 0x0E); @@ -1306,6 +1311,10 @@ static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags) ldm_error ("A VBLK claims to have %d parts.", num); return false; } + if (rec >= num) { + ldm_error("REC value (%d) exceeds NUM value (%d)", rec, num); + return false; + } list_for_each (item, frags) { f = list_entry (item, struct frag, list); @@ -1334,10 +1343,9 @@ found: f->map |= (1 << rec); - if (num > 0) { - data += VBLK_SIZE_HEAD; - size -= VBLK_SIZE_HEAD; - } + data += VBLK_SIZE_HEAD; + size -= VBLK_SIZE_HEAD; + memcpy (f->data+rec*(size-VBLK_SIZE_HEAD)+VBLK_SIZE_HEAD, data, size); return true; -- cgit v1.2.3 From 794680366c045e368ecbec6f1729745b4f5b00ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Piel?= Date: Thu, 5 Aug 2010 23:51:49 -0700 Subject: Input: elantech - discard the first 2 positions on some firmwares MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7f29f17b57255b6395046805a98bc663ded63fb8 upstream. According to the Dell/Ubuntu driver, what was previously observed as "jumpy cursor" corresponds to the hardware sending incorrect data for the first two reports of a one touch finger. So let's use the same workaround as in the other driver. Also, detect another firmware version with the same behaviour, as in the other driver. Signed-off-by: Éric Piel Signed-off-by: Dmitry Torokhov Signed-off-by: Andi Kleen [bwh: Adjust for 2.6.32] [ak: adjust for 2.6.35] Signed-off-by: Greg Kroah-Hartman --- drivers/input/mouse/elantech.c | 26 +++++++++++++------------- drivers/input/mouse/elantech.h | 7 ++++--- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index b18862b2a70e..b188fd747c93 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -185,7 +185,6 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) struct elantech_data *etd = psmouse->private; unsigned char *packet = psmouse->packet; int fingers; - static int old_fingers; if (etd->fw_version < 0x020000) { /* @@ -203,11 +202,14 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) } if (etd->jumpy_cursor) { - /* Discard packets that are likely to have bogus coordinates */ - if (fingers > old_fingers) { - elantech_debug("discarding packet\n"); - goto discard_packet_v1; - } + if (fingers != 1) { + etd->single_finger_reports = 0; + } else if (etd->single_finger_reports < 2) { + /* Discard first 2 reports of one finger, bogus */ + etd->single_finger_reports++; + elantech_debug("elantech.c: discarding packet\n"); + return; + } } input_report_key(dev, BTN_TOUCH, fingers != 0); @@ -238,9 +240,6 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) } input_sync(dev); - - discard_packet_v1: - old_fingers = fingers; } /* @@ -733,13 +732,14 @@ int elantech_init(struct psmouse *psmouse) etd->capabilities = param[0]; /* - * This firmware seems to suffer from misreporting coordinates when + * This firmware suffers from misreporting coordinates when * a touch action starts causing the mouse cursor or scrolled page * to jump. Enable a workaround. */ - if (etd->fw_version == 0x020022) { - pr_info("firmware version 2.0.34 detected, enabling jumpy cursor workaround\n"); - etd->jumpy_cursor = 1; + if (etd->fw_version == 0x020022 || etd->fw_version == 0x020600) { + pr_info("elantech.c: firmware version 2.0.34/2.6.0 detected, " + "enabling jumpy cursor workaround\n"); + etd->jumpy_cursor = true; } if (elantech_set_absolute_mode(psmouse)) { diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index ac57bde1bb9f..aa4aac5d2198 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h @@ -100,10 +100,11 @@ struct elantech_data { unsigned char reg_26; unsigned char debug; unsigned char capabilities; - unsigned char paritycheck; - unsigned char jumpy_cursor; + bool paritycheck; + bool jumpy_cursor; unsigned char hw_version; - unsigned int fw_version; + unsigned int fw_version; + unsigned int single_finger_reports; unsigned char parity[256]; }; -- cgit v1.2.3 From fcf7b1d0968525a94e174b8fb50f0f81e130efe1 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 25 May 2010 04:20:30 +0100 Subject: Staging: rtl8192su: Clean up in case of an error in module initialisation commit 9a3dfa0555130952517b9a9c3918729495aa709a upstream. Currently various resources may be leaked in case of an error. Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/rtl8192su/r8192U_core.c | 43 +++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index 1b6890611fb6..31a2cc7b61c3 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c @@ -991,10 +991,11 @@ static int proc_get_stats_rx(char *page, char **start, return len; } -void rtl8192_proc_module_init(void) +int rtl8192_proc_module_init(void) { RT_TRACE(COMP_INIT, "Initializing proc filesystem"); rtl8192_proc=create_proc_entry(RTL819xU_MODULE_NAME, S_IFDIR, init_net.proc_net); + return rtl8192_proc ? 0 : -ENOMEM; } @@ -7474,35 +7475,63 @@ static int __init rtl8192_usb_module_init(void) ret = ieee80211_crypto_init(); if (ret) { printk(KERN_ERR "ieee80211_crypto_init() failed %d\n", ret); - return ret; + goto fail_crypto; } ret = ieee80211_crypto_tkip_init(); if (ret) { printk(KERN_ERR "ieee80211_crypto_tkip_init() failed %d\n", ret); - return ret; + goto fail_crypto_tkip; } ret = ieee80211_crypto_ccmp_init(); if (ret) { printk(KERN_ERR "ieee80211_crypto_ccmp_init() failed %d\n", ret); - return ret; + goto fail_crypto_ccmp; } ret = ieee80211_crypto_wep_init(); if (ret) { printk(KERN_ERR "ieee80211_crypto_wep_init() failed %d\n", ret); - return ret; + goto fail_crypto_wep; } printk(KERN_INFO "\nLinux kernel driver for RTL8192 based WLAN cards\n"); printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan\n"); RT_TRACE(COMP_INIT, "Initializing module"); RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT); - rtl8192_proc_module_init(); - return usb_register(&rtl8192_usb_driver); + + ret = rtl8192_proc_module_init(); + if (ret) { + pr_err("rtl8192_proc_module_init() failed %d\n", ret); + goto fail_proc; + } + + ret = usb_register(&rtl8192_usb_driver); + if (ret) { + pr_err("usb_register() failed %d\n", ret); + goto fail_usb; + } + + return 0; + +fail_usb: + rtl8192_proc_module_remove(); +fail_proc: + ieee80211_crypto_wep_exit(); +fail_crypto_wep: + ieee80211_crypto_ccmp_exit(); +fail_crypto_ccmp: + ieee80211_crypto_tkip_exit(); +fail_crypto_tkip: + ieee80211_crypto_deinit(); +fail_crypto: +#ifdef CONFIG_IEEE80211_DEBUG + ieee80211_debug_exit(); +#endif + return ret; } -- cgit v1.2.3 From f67e667fdbefbfaad3eb37c2d0a8ca9d74b34300 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 25 May 2010 04:25:57 +0100 Subject: Staging: rtl8192su: Fix procfs code for interfaces not named wlan0 commit 41a38d9e632f7c9ec5ad8fc627567d97f4302c4a upstream. The current code creates directories in procfs named after interfaces, but doesn't handle renaming. This can result in name collisions and consequent WARNINGs. It also means that the interface name cannot reliably be used to remove the directory - in fact the current code doesn't even try, and always uses "wlan0"! Since the name of a proc_dir_entry is embedded in it, use that when removing it. Add a netdev notifier to catch interface renaming, and remove and re-add the directory at this point. Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/rtl8192su/r8192U_core.c | 35 ++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index 31a2cc7b61c3..9fbb48d64409 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c @@ -27,6 +27,7 @@ #include #include #include +#include #undef LOOP_TEST #undef DUMP_RX @@ -162,6 +163,8 @@ MODULE_PARM_DESC(channels," Channel bitmask for specific locales. NYI"); static int __devinit rtl8192_usb_probe(struct usb_interface *intf, const struct usb_device_id *id); static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf); +static const struct net_device_ops rtl8192_netdev_ops; +static struct notifier_block proc_netdev_notifier; static struct usb_driver rtl8192_usb_driver = { .name = RTL819xU_MODULE_NAME, /* Driver name */ @@ -993,14 +996,22 @@ static int proc_get_stats_rx(char *page, char **start, int rtl8192_proc_module_init(void) { + int ret; + RT_TRACE(COMP_INIT, "Initializing proc filesystem"); rtl8192_proc=create_proc_entry(RTL819xU_MODULE_NAME, S_IFDIR, init_net.proc_net); - return rtl8192_proc ? 0 : -ENOMEM; + if (!rtl8192_proc) + return -ENOMEM; + ret = register_netdevice_notifier(&proc_netdev_notifier); + if (ret) + remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net); + return ret; } void rtl8192_proc_module_remove(void) { + unregister_netdevice_notifier(&proc_netdev_notifier); remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net); } @@ -1028,8 +1039,7 @@ void rtl8192_proc_remove_one(struct net_device *dev) remove_proc_entry("registers-e", priv->dir_dev); // remove_proc_entry("cck-registers",priv->dir_dev); // remove_proc_entry("ofdm-registers",priv->dir_dev); - //remove_proc_entry(dev->name, rtl8192_proc); - remove_proc_entry("wlan0", rtl8192_proc); + remove_proc_entry(priv->dir_dev->name, rtl8192_proc); priv->dir_dev = NULL; } } @@ -1146,6 +1156,25 @@ void rtl8192_proc_init_one(struct net_device *dev) dev->name); } } + +static int proc_netdev_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct net_device *net_dev = ptr; + + if (net_dev->netdev_ops == &rtl8192_netdev_ops && + event == NETDEV_CHANGENAME) { + rtl8192_proc_remove_one(net_dev); + rtl8192_proc_init_one(net_dev); + } + + return NOTIFY_DONE; +} + +static struct notifier_block proc_netdev_notifier = { + .notifier_call = proc_netdev_event, +}; + /**************************************************************************** -----------------------------MISC STUFF------------------------- *****************************************************************************/ -- cgit v1.2.3 From d757e9ae3da24bf77e41d76fefcc3e07581f1834 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 13 Sep 2010 14:43:25 -0400 Subject: USB: teach "devices" file about Wireless and SuperSpeed USB commit 834e2312e7a384877a876b0d34dffc3046c96bcb upstream. USB: teach "devices" file about Wireless and SuperSpeed USB The /sys/kernel/debug/usb/devices file doesn't know about Wireless or SuperSpeed USB. This patch (as1416b) teaches it, and updates the Documentation/usb/proc_sub_info.txt file accordingly. Signed-off-by: Alan Stern Signed-off-by: Andi Kleen CC: David Vrabel CC: Sarah Sharp Signed-off-by: Greg Kroah-Hartman [Julien Blache: The original commit also added the correct speed for USB_SPEED_WIRELESS, I removed it as it's not supported in 2.6.32.] Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/proc_usb_info.txt | 34 ++++++++++++++++++++++------------ drivers/usb/core/devices.c | 10 ++++++---- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/Documentation/usb/proc_usb_info.txt b/Documentation/usb/proc_usb_info.txt index fafcd4723260..afe596d5f201 100644 --- a/Documentation/usb/proc_usb_info.txt +++ b/Documentation/usb/proc_usb_info.txt @@ -1,12 +1,17 @@ /proc/bus/usb filesystem output =============================== -(version 2003.05.30) +(version 2010.09.13) The usbfs filesystem for USB devices is traditionally mounted at /proc/bus/usb. It provides the /proc/bus/usb/devices file, as well as the /proc/bus/usb/BBB/DDD files. +In many modern systems the usbfs filsystem isn't used at all. Instead +USB device nodes are created under /dev/usb/ or someplace similar. The +"devices" file is available in debugfs, typically as +/sys/kernel/debug/usb/devices. + **NOTE**: If /proc/bus/usb appears empty, and a host controller driver has been linked, then you need to mount the @@ -106,8 +111,8 @@ Legend: Topology info: -T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd -| | | | | | | | |__MaxChildren +T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd +| | | | | | | | |__MaxChildren | | | | | | | |__Device Speed in Mbps | | | | | | |__DeviceNumber | | | | | |__Count of devices at this level @@ -120,8 +125,13 @@ T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd Speed may be: 1.5 Mbit/s for low speed USB 12 Mbit/s for full speed USB - 480 Mbit/s for high speed USB (added for USB 2.0) + 480 Mbit/s for high speed USB (added for USB 2.0); + also used for Wireless USB, which has no fixed speed + 5000 Mbit/s for SuperSpeed USB (added for USB 3.0) + For reasons lost in the mists of time, the Port number is always + too low by 1. For example, a device plugged into port 4 will + show up with "Port=03". Bandwidth info: B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd @@ -291,7 +301,7 @@ Here's an example, from a system which has a UHCI root hub, an external hub connected to the root hub, and a mouse and a serial converter connected to the external hub. -T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 +T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 B: Alloc= 28/900 us ( 3%), #Int= 2, #Iso= 0 D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=0000 ProdID=0000 Rev= 0.00 @@ -301,21 +311,21 @@ C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms -T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4 +T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4 D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=0451 ProdID=1446 Rev= 1.00 C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms -T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0 +T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0 D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=04b4 ProdID=0001 Rev= 0.00 C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse E: Ad=81(I) Atr=03(Int.) MxPS= 3 Ivl= 10ms -T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 +T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=0565 ProdID=0001 Rev= 1.08 S: Manufacturer=Peracom Networks, Inc. @@ -330,12 +340,12 @@ E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl= 8ms Selecting only the "T:" and "I:" lines from this (for example, by using "procusb ti"), we have: -T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 -T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4 +T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 +T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4 I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub -T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0 +T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0 I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse -T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 +T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 I: If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index dcb4e5ed0a08..46e1d130c640 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -66,8 +66,8 @@ #define ALLOW_SERIAL_NUMBER static const char *format_topo = -/* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */ -"\nT: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n"; +/* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd */ +"\nT: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%-4s MxCh=%2d\n"; static const char *format_string_manufacturer = /* S: Manufacturer=xxxx */ @@ -521,11 +521,13 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, speed = "1.5"; break; case USB_SPEED_UNKNOWN: /* usb 1.1 root hub code */ case USB_SPEED_FULL: - speed = "12 "; break; + speed = "12"; break; case USB_SPEED_HIGH: speed = "480"; break; + case USB_SPEED_SUPER: + speed = "5000"; break; default: - speed = "?? "; + speed = "??"; } data_end = pages_start + sprintf(pages_start, format_topo, bus->busnum, level, parent_devnum, -- cgit v1.2.3 From cfdbc9ddef0d0f3d7b4423af1f243d17643f6c3f Mon Sep 17 00:00:00 2001 From: Andy Chittenden Date: Tue, 10 Aug 2010 10:19:53 -0400 Subject: SUNRPC: fix NFS client over TCP hangs due to packet loss (Bug 16494) commit 669502ff31d7dba1849aec7ee2450a3c61f57d39 upstream. When reusing a TCP connection, ensure that it's aborted if a previous shutdown attempt has been made on that connection so that the RPC over TCP recovery mechanism succeeds. Signed-off-by: Andy Chittenden Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/sunrpc/xprtsock.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 02fbb8dc288c..ce838698723e 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1307,10 +1307,11 @@ static void xs_tcp_state_change(struct sock *sk) if (!(xprt = xprt_from_sock(sk))) goto out; dprintk("RPC: xs_tcp_state_change client %p...\n", xprt); - dprintk("RPC: state %x conn %d dead %d zapped %d\n", + dprintk("RPC: state %x conn %d dead %d zapped %d sk_shutdown %d\n", sk->sk_state, xprt_connected(xprt), sock_flag(sk, SOCK_DEAD), - sock_flag(sk, SOCK_ZAPPED)); + sock_flag(sk, SOCK_ZAPPED), + sk->sk_shutdown); switch (sk->sk_state) { case TCP_ESTABLISHED: @@ -1781,10 +1782,25 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt, struct sock_xprt *tra { unsigned int state = transport->inet->sk_state; - if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED) - return; - if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT)) - return; + if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED) { + /* we don't need to abort the connection if the socket + * hasn't undergone a shutdown + */ + if (transport->inet->sk_shutdown == 0) + return; + dprintk("RPC: %s: TCP_CLOSEd and sk_shutdown set to %d\n", + __func__, transport->inet->sk_shutdown); + } + if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT)) { + /* we don't need to abort the connection if the socket + * hasn't undergone a shutdown + */ + if (transport->inet->sk_shutdown == 0) + return; + dprintk("RPC: %s: ESTABLISHED/SYN_SENT " + "sk_shutdown set to %d\n", + __func__, transport->inet->sk_shutdown); + } xs_abort_connection(xprt, transport); } -- cgit v1.2.3 From 96f19d2bbf2bd7405cde6de18378276267015c04 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Fri, 4 Mar 2011 19:26:03 -0500 Subject: nfs4: Ensure that ACL pages sent over NFS were not allocated from the slab (v3) commit e9e3d724e2145f5039b423c290ce2b2c3d8f94bc upstream. The "bad_page()" page allocator sanity check was reported recently (call chain as follows): bad_page+0x69/0x91 free_hot_cold_page+0x81/0x144 skb_release_data+0x5f/0x98 __kfree_skb+0x11/0x1a tcp_ack+0x6a3/0x1868 tcp_rcv_established+0x7a6/0x8b9 tcp_v4_do_rcv+0x2a/0x2fa tcp_v4_rcv+0x9a2/0x9f6 do_timer+0x2df/0x52c ip_local_deliver+0x19d/0x263 ip_rcv+0x539/0x57c netif_receive_skb+0x470/0x49f :virtio_net:virtnet_poll+0x46b/0x5c5 net_rx_action+0xac/0x1b3 __do_softirq+0x89/0x133 call_softirq+0x1c/0x28 do_softirq+0x2c/0x7d do_IRQ+0xec/0xf5 default_idle+0x0/0x50 ret_from_intr+0x0/0xa default_idle+0x29/0x50 cpu_idle+0x95/0xb8 start_kernel+0x220/0x225 _sinittext+0x22f/0x236 It occurs because an skb with a fraglist was freed from the tcp retransmit queue when it was acked, but a page on that fraglist had PG_Slab set (indicating it was allocated from the Slab allocator (which means the free path above can't safely free it via put_page. We tracked this back to an nfsv4 setacl operation, in which the nfs code attempted to fill convert the passed in buffer to an array of pages in __nfs4_proc_set_acl, which gets used by the skb->frags list in xs_sendpages. __nfs4_proc_set_acl just converts each page in the buffer to a page struct via virt_to_page, but the vfs allocates the buffer via kmalloc, meaning the PG_slab bit is set. We can't create a buffer with kmalloc and free it later in the tcp ack path with put_page, so we need to either: 1) ensure that when we create the list of pages, no page struct has PG_Slab set or 2) not use a page list to send this data Given that these buffers can be multiple pages and arbitrarily sized, I think (1) is the right way to go. I've written the below patch to allocate a page from the buddy allocator directly and copy the data over to it. This ensures that we have a put_page free-able page for every entry that winds up on an skb frag list, so it can be safely freed when the frame is acked. We do a put page on each entry after the rpc_call_sync call so as to drop our own reference count to the page, leaving only the ref count taken by tcp_sendpages. This way the data will be properly freed when the ack comes in Successfully tested by myself to solve the above oops. Note, as this is the result of a setacl operation that exceeded a page of data, I think this amounts to a local DOS triggerable by an uprivlidged user, so I'm CCing security on this as well. Signed-off-by: Neil Horman Signed-off-by: Andi Kleen CC: Trond Myklebust CC: security@kernel.org CC: Jeff Layton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index f7b7698cd9a7..b9f6ab66b142 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3275,6 +3275,35 @@ static void buf_to_pages(const void *buf, size_t buflen, } } +static int buf_to_pages_noslab(const void *buf, size_t buflen, + struct page **pages, unsigned int *pgbase) +{ + struct page *newpage, **spages; + int rc = 0; + size_t len; + spages = pages; + + do { + len = min(PAGE_CACHE_SIZE, buflen); + newpage = alloc_page(GFP_KERNEL); + + if (newpage == NULL) + goto unwind; + memcpy(page_address(newpage), buf, len); + buf += len; + buflen -= len; + *pages++ = newpage; + rc++; + } while (buflen != 0); + + return rc; + +unwind: + for(; rc > 0; rc--) + __free_page(spages[rc-1]); + return -ENOMEM; +} + struct nfs4_cached_acl { int cached; size_t len; @@ -3441,13 +3470,23 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl .rpc_argp = &arg, .rpc_resp = &res, }; - int ret; + int ret, i; if (!nfs4_server_supports_acls(server)) return -EOPNOTSUPP; + i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase); + if (i < 0) + return i; nfs_inode_return_delegation(inode); - buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); ret = nfs4_call_sync(server, &msg, &arg, &res, 1); + + /* + * Free each page after tx, so the only ref left is + * held by the network stack + */ + for (; i > 0; i--) + put_page(pages[i-1]); + nfs_access_zap_cache(inode); nfs_zap_acl_cache(inode); return ret; -- cgit v1.2.3 From 36a01162f9a6d45d87ffe118f72ec9bc9853acdf Mon Sep 17 00:00:00 2001 From: Jovi Zhang Date: Wed, 2 Mar 2011 23:19:37 +0000 Subject: nfs: fix compilation warning commit 43b7c3f051dea504afccc39bcb56d8e26c2e0b77 upstream. this commit fix compilation warning as following: linux-2.6/fs/nfs/nfs4proc.c:3265: warning: comparison of distinct pointer types lacks a cast Signed-off-by: Jovi Zhang Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/nfs/nfs4proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index b9f6ab66b142..80943d88252a 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3284,7 +3284,7 @@ static int buf_to_pages_noslab(const void *buf, size_t buflen, spages = pages; do { - len = min(PAGE_CACHE_SIZE, buflen); + len = min_t(size_t, PAGE_CACHE_SIZE, buflen); newpage = alloc_page(GFP_KERNEL); if (newpage == NULL) -- cgit v1.2.3 From 5b1157fecf0ced4dd3c447866c332a6d9f9979ec Mon Sep 17 00:00:00 2001 From: Timo Warns Date: Mon, 14 Mar 2011 14:59:33 +0100 Subject: Fix corrupted OSF partition table parsing commit 1eafbfeb7bdf59cfe173304c76188f3fd5f1fd05 upstream. The kernel automatically evaluates partition tables of storage devices. The code for evaluating OSF partitions contains a bug that leaks data from kernel heap memory to userspace for certain corrupted OSF partitions. In more detail: for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) { iterates from 0 to d_npartitions - 1, where d_npartitions is read from the partition table without validation and partition is a pointer to an array of at most 8 d_partitions. Add the proper and obvious validation. Signed-off-by: Timo Warns Cc: stable@kernel.org Signed-off-by: Andi Kleen [ Changed the patch trivially to not repeat the whole le16_to_cpu() thing, and to use an explicit constant for the magic value '8' ] Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/partitions/osf.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/fs/partitions/osf.c b/fs/partitions/osf.c index fc22b85d436a..5b49d40ff993 100644 --- a/fs/partitions/osf.c +++ b/fs/partitions/osf.c @@ -10,10 +10,13 @@ #include "check.h" #include "osf.h" +#define MAX_OSF_PARTITIONS 8 + int osf_partition(struct parsed_partitions *state) { int i; int slot = 1; + unsigned int npartitions; Sector sect; unsigned char *data; struct disklabel { @@ -45,7 +48,7 @@ int osf_partition(struct parsed_partitions *state) u8 p_fstype; u8 p_frag; __le16 p_cpg; - } d_partitions[8]; + } d_partitions[MAX_OSF_PARTITIONS]; } * label; struct d_partition * partition; @@ -63,7 +66,12 @@ int osf_partition(struct parsed_partitions *state) put_dev_sector(sect); return 0; } - for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) { + npartitions = le16_to_cpu(label->d_npartitions); + if (npartitions > MAX_OSF_PARTITIONS) { + put_dev_sector(sect); + return 0; + } + for (i = 0 ; i < npartitions; i++, partition++) { if (slot == state->limit) break; if (le32_to_cpu(partition->p_size)) -- cgit v1.2.3 From 6a469c129ce3fd551dfb9a2f99e4a1785add9b8b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 16 Mar 2011 08:04:07 -0700 Subject: Increase OSF partition limit from 8 to 18 commit 34d211a2d5df4984a35b18d8ccacbe1d10abb067 upstream. It turns out that while a maximum of 8 partitions may be what people "should" have had, you can actually fit up to 18 entries(*) in a sector. And some people clearly were taking advantage of that, like Michael Cree, who had ten partitions on one of his OSF disks. (*) The OSF partition data starts at byte offset 64 in the first sector, and the array of 16-byte partition entries start at offset 148 in the on-disk partition structure. Reported-by: Michael Cree Cc: stable@kernel.org (v2.6.38) Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/partitions/osf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/partitions/osf.c b/fs/partitions/osf.c index 5b49d40ff993..5f71c928af76 100644 --- a/fs/partitions/osf.c +++ b/fs/partitions/osf.c @@ -10,7 +10,7 @@ #include "check.h" #include "osf.h" -#define MAX_OSF_PARTITIONS 8 +#define MAX_OSF_PARTITIONS 18 int osf_partition(struct parsed_partitions *state) { -- cgit v1.2.3 From 16d34d5899c57d0f1a1916cdde3a017d497c57db Mon Sep 17 00:00:00 2001 From: Edgar Hucek Date: Tue, 9 Nov 2010 15:15:01 +0000 Subject: hwmon: (applesmc) Add MacBookAir3,1(3,2) support commit 132af03233b493101a53010383b5abb5b9ff1e51 upstream. This patch add support for the MacBookAir3,1 and MacBookAir3,2 to the applesmc driver. [rydberg@euromail.se: minor cleanup] Signed-off-by: Edgar Hucek Signed-off-by: Henrik Rydberg Signed-off-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/hwmon/applesmc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index b6598aa557a0..d616174807a1 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -162,6 +162,10 @@ static const char *temperature_sensors_sets[][41] = { /* Set 22: MacBook Pro 7,1 */ { "TB0T", "TB1T", "TB2T", "TC0D", "TC0P", "TN0D", "TN0P", "TN0S", "TN1D", "TN1F", "TN1G", "TN1S", "Th1H", "Ts0P", "Ts0S", NULL }, +/* Set 23: MacBook Air 3,1 */ + { "TB0T", "TB1T", "TB2T", "TC0D", "TC0E", "TC0P", "TC1E", "TCZ3", + "TCZ4", "TCZ5", "TG0E", "TG1E", "TG2E", "TGZ3", "TGZ4", "TGZ5", + "TH0F", "TH0O", "TM0P" }, }; /* List of keys used to read/write fan speeds */ @@ -1524,11 +1528,17 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { { .accelerometer = 1, .light = 1, .temperature_set = 21 }, /* MacBook Pro 7,1: accelerometer, backlight and temperature set 22 */ { .accelerometer = 1, .light = 1, .temperature_set = 22 }, +/* MacBook Air 3,1: accelerometer, backlight and temperature set 23 */ + { .accelerometer = 0, .light = 0, .temperature_set = 23 }, }; /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". * So we need to put "Apple MacBook Pro" before "Apple MacBook". */ static __initdata struct dmi_system_id applesmc_whitelist[] = { + { applesmc_dmi_match, "Apple MacBook Air 3", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir3") }, + &applesmc_dmi_data[23]}, { applesmc_dmi_match, "Apple MacBook Air 2", { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir2") }, -- cgit v1.2.3 From 64c2138f28bf463cad14d5772c4fce45557e2319 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 12 Sep 2010 02:41:47 +0100 Subject: ALSA: emux: Add trivial compat ioctl handler commit a254dba37c5a372fc8b44ba29509ba052d4e859d upstream. Reported-by: Carmen Cru Signed-off-by: Ben Hutchings Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/synth/emux/emux_hwdep.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c index ff0b2a8fd25b..5ae1eae9f6db 100644 --- a/sound/synth/emux/emux_hwdep.c +++ b/sound/synth/emux/emux_hwdep.c @@ -128,6 +128,9 @@ snd_emux_init_hwdep(struct snd_emux *emu) strcpy(hw->name, SNDRV_EMUX_HWDEP_NAME); hw->iface = SNDRV_HWDEP_IFACE_EMUX_WAVETABLE; hw->ops.ioctl = snd_emux_hwdep_ioctl; + /* The ioctl parameter types are compatible between 32- and + * 64-bit architectures, so use the same function. */ + hw->ops.ioctl_compat = snd_emux_hwdep_ioctl; hw->exclusive = 1; hw->private_data = emu; if ((err = snd_card_register(emu->card)) < 0) -- cgit v1.2.3 From 119954a2394575debafc7c0c4071363fc9076cb5 Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Wed, 22 Sep 2010 17:31:37 -0400 Subject: ALSA: hda - MacBookPro 5,3 line-in support commit 4e7d7c6018567fa03f387d06602d4145c75ebbe0 upstream. I've found the following patch is necessary to enable line-in on my MacBookPro 5,3 machine. With the patch applied I've successfully recorded audio from the line-in jack. This is based on the existing 5,5 support. Signed-off-by: Vince Weaver Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_cirrus.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 059565f10ee9..370933ccd387 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -65,6 +65,7 @@ struct cs_spec { /* available models */ enum { + CS420X_MBP53, CS420X_MBP55, CS420X_IMAC27, CS420X_AUTO, @@ -838,7 +839,8 @@ static void cs_automute(struct hda_codec *codec) AC_VERB_SET_PIN_WIDGET_CONTROL, hp_present ? 0 : PIN_OUT); } - if (spec->board_config == CS420X_MBP55 || + if (spec->board_config == CS420X_MBP53 || + spec->board_config == CS420X_MBP55 || spec->board_config == CS420X_IMAC27) { unsigned int gpio = hp_present ? 0x02 : 0x08; snd_hda_codec_write(codec, 0x01, 0, @@ -1130,6 +1132,7 @@ static int cs_parse_auto_config(struct hda_codec *codec) } static const char *cs420x_models[CS420X_MODELS] = { + [CS420X_MBP53] = "mbp53", [CS420X_MBP55] = "mbp55", [CS420X_IMAC27] = "imac27", [CS420X_AUTO] = "auto", @@ -1137,6 +1140,7 @@ static const char *cs420x_models[CS420X_MODELS] = { static struct snd_pci_quirk cs420x_cfg_tbl[] = { + SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53), SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), {} /* terminator */ @@ -1147,6 +1151,20 @@ struct cs_pincfg { u32 val; }; +static struct cs_pincfg mbp53_pincfgs[] = { + { 0x09, 0x012b4050 }, + { 0x0a, 0x90100141 }, + { 0x0b, 0x90100140 }, + { 0x0c, 0x018b3020 }, + { 0x0d, 0x90a00110 }, + { 0x0e, 0x400000f0 }, + { 0x0f, 0x01cbe030 }, + { 0x10, 0x014be060 }, + { 0x12, 0x400000f0 }, + { 0x15, 0x400000f0 }, + {} /* terminator */ +}; + static struct cs_pincfg mbp55_pincfgs[] = { { 0x09, 0x012b4030 }, { 0x0a, 0x90100121 }, @@ -1176,6 +1194,7 @@ static struct cs_pincfg imac27_pincfgs[] = { }; static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { + [CS420X_MBP53] = mbp53_pincfgs, [CS420X_MBP55] = mbp55_pincfgs, [CS420X_IMAC27] = imac27_pincfgs, }; @@ -1208,6 +1227,7 @@ static int patch_cs420x(struct hda_codec *codec) switch (spec->board_config) { case CS420X_IMAC27: + case CS420X_MBP53: case CS420X_MBP55: /* GPIO1 = headphones */ /* GPIO3 = speakers */ -- cgit v1.2.3 From eb918d171083f46813b93c9dd458f98c14189fdf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 11 Oct 2010 14:46:35 +0200 Subject: ALSA: hda - Add model=mbp55 entry for MacBookPro 7,1 commit f46119b73425df9d1e05c5d5e909a993d95b0218 upstream. Reference: Novell bnc#645066 https://bugzilla.novell.com/show_bug.cgi?id=645066 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_cirrus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 370933ccd387..d6d259517ba8 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -1142,6 +1142,7 @@ static const char *cs420x_models[CS420X_MODELS] = { static struct snd_pci_quirk cs420x_cfg_tbl[] = { SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53), SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), + SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55), SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), {} /* terminator */ }; -- cgit v1.2.3 From abf99a8ea6970057d8d7ca93ac1629fe55b65162 Mon Sep 17 00:00:00 2001 From: "Edgar (gimli) Hucek" Date: Wed, 3 Nov 2010 08:14:10 +0100 Subject: ALSA: hda - MacBookAir3,1(3,2) alsa support commit 87232dd49aeb6b7d1af291edca8bd129a82ef4b5 upstream. This patch add support for the MacBookAir3,1 and MacBookAir3,2 to the alsa sound system. Signed-off-by: Edgar (gimli) Hucek Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_cirrus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index d6d259517ba8..44427c1802e1 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -1141,6 +1141,7 @@ static const char *cs420x_models[CS420X_MODELS] = { static struct snd_pci_quirk cs420x_cfg_tbl[] = { SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53), + SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55), SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55), SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), -- cgit v1.2.3 From 23046c654496911b478402ae7cd0909f64c3f712 Mon Sep 17 00:00:00 2001 From: Bruce Rogers Date: Thu, 10 Feb 2011 11:03:31 -0800 Subject: virtio_net: Add schedule check to napi_enable call commit 3e9d08ec0a68f6faf718d5a7e050fe5ca0ba004f upstream. Under harsh testing conditions, including low memory, the guest would stop receiving packets. With this patch applied we no longer see any problems in the driver while performing these tests for extended periods of time. Make sure napi is scheduled subsequent to each napi_enable. Signed-off-by: Bruce Rogers Signed-off-by: Olaf Kirch Signed-off-by: Rusty Russell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen [bwh: Adjust for 2.6.32] Signed-off-by: Greg Kroah-Hartman --- drivers/net/virtio_net.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index bb6b67f6b0cc..1cf8da8f361a 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -446,6 +446,20 @@ static void skb_recv_done(struct virtqueue *rvq) } } +static void virtnet_napi_enable(struct virtnet_info *vi) +{ + napi_enable(&vi->napi); + + /* If all buffers were filled by other side before we napi_enabled, we + * won't get another interrupt, so process any outstanding packets + * now. virtnet_poll wants re-enable the queue, so we disable here. + * We synchronize against interrupts via NAPI_STATE_SCHED */ + if (napi_schedule_prep(&vi->napi)) { + virtqueue_disable_cb(vi->rvq); + __napi_schedule(&vi->napi); + } +} + static void refill_work(struct work_struct *work) { struct virtnet_info *vi; @@ -454,7 +468,7 @@ static void refill_work(struct work_struct *work) vi = container_of(work, struct virtnet_info, refill.work); napi_disable(&vi->napi); still_empty = !try_fill_recv(vi, GFP_KERNEL); - napi_enable(&vi->napi); + virtnet_napi_enable(vi); /* In theory, this can happen: if we don't get any buffers in * we will *never* try to fill again. */ @@ -638,16 +652,7 @@ static int virtnet_open(struct net_device *dev) { struct virtnet_info *vi = netdev_priv(dev); - napi_enable(&vi->napi); - - /* If all buffers were filled by other side before we napi_enabled, we - * won't get another interrupt, so process any outstanding packets - * now. virtnet_poll wants re-enable the queue, so we disable here. - * We synchronize against interrupts via NAPI_STATE_SCHED */ - if (napi_schedule_prep(&vi->napi)) { - virtqueue_disable_cb(vi->rvq); - __napi_schedule(&vi->napi); - } + virtnet_napi_enable(vi); return 0; } -- cgit v1.2.3 From ee272756b11915f4711da8ba0b79f7ae1c127666 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Fri, 20 Aug 2010 16:24:06 +0900 Subject: Bluetooth: Add support Bluetooth controller of MacbookPro 6,2 commit 9c047157a20521cd525527947b13b950d168d2e6 upstream. Bluetooth controller of MacbookPro 6,2 does not work. Because Device Class of these controllers was set 255 (Vendor Sepecific Class). T: Bus=01 Lev=03 Prnt=03 Port=02 Cnt=03 Dev#= 8 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=05ac ProdID=8218 Rev=00.22 S: Manufacturer=Apple Inc. S: Product=Bluetooth USB Host Controller C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=0mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none) I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) Signed-off-by: Nobuhiro Iwamatsu Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index c9e2dc830b22..92d661776bc7 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -62,6 +62,9 @@ static struct usb_device_id btusb_table[] = { /* Apple iMac11,1 */ { USB_DEVICE(0x05ac, 0x8215) }, + /* Apple MacBookPro6,2 */ + { USB_DEVICE(0x05ac, 0x8218) }, + /* Apple MacBookPro8,2 */ { USB_DEVICE(0x05ac, 0x821a) }, -- cgit v1.2.3 From 2c2f8644ed699331316b5479f570c4b99e813064 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Fri, 20 Aug 2010 16:24:07 +0900 Subject: Bluetooth: Add support Bluetooth controller of MacbookPro 7,1 commit 3cd01976e702ccaffb907727caff4f8789353599 upstream. Bluetooth controller of MacbookPro 7,1 does not work. Because Device Class of these controllers was set 255 (Vendor Sepecific Class). T: Bus=04 Lev=02 Prnt=04 Port=00 Cnt=01 Dev#= 5 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=05ac ProdID=8213 Rev=01.86 S: Manufacturer=Apple Inc. S: Product=Bluetooth USB Host Controller S: SerialNumber=5C5948C81B99 C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=0mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=00 Driver=(none) Signed-off-by: Nobuhiro Iwamatsu Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 92d661776bc7..d42dbeba2370 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -59,6 +59,9 @@ static struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, + /* Apple MacBookPro 7,1 */ + { USB_DEVICE(0x05ac, 0x8213) }, + /* Apple iMac11,1 */ { USB_DEVICE(0x05ac, 0x8215) }, -- cgit v1.2.3 From d7f29871274f6898ad4a75af91c329e8889cddfd Mon Sep 17 00:00:00 2001 From: "Edgar (gimli) Hucek" Date: Thu, 4 Nov 2010 08:04:33 +0100 Subject: Bluetooth: Add MacBookAir3,1(2) support commit 3e3ede7dda2d77d2cbec608e663b6a6ace501bfc upstream. Adding the new MacBookAir3,1(2) to btusb. Output without the patch and btusb loaded : T: Bus=03 Lev=02 Prnt=03 Port=02 Cnt=01 Dev#= 6 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=05ac ProdID=821b Rev= 0.34 S: Manufacturer=Apple Inc. S: Product=Bluetooth USB Host Controller C:* #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr= 0mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none) E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none) E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none) E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none) E: Ad=83(I) Atr=01(Isoc) MxPS= 32 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 32 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none) E: Ad=83(I) Atr=01(Isoc) MxPS= 64 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 64 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none) E: Ad=83(I) Atr=01(Isoc) MxPS= 64 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 64 Ivl=1ms I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) Output with the patch and btusb loaded : T: Bus=03 Lev=02 Prnt=03 Port=02 Cnt=01 Dev#= 6 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=05ac ProdID=821b Rev= 0.34 S: Manufacturer=Apple Inc. S: Product=Bluetooth USB Host Controller C:* #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr= 0mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 32 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 32 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 64 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 64 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 64 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 64 Ivl=1ms I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) Signed-off-by: Edgar (gimli) Hucek Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index d42dbeba2370..468a940f574b 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -68,6 +68,9 @@ static struct usb_device_id btusb_table[] = { /* Apple MacBookPro6,2 */ { USB_DEVICE(0x05ac, 0x8218) }, + /* Apple MacBookAir3,1, MacBookAir3,2 */ + { USB_DEVICE(0x05ac, 0x821b) }, + /* Apple MacBookPro8,2 */ { USB_DEVICE(0x05ac, 0x821a) }, -- cgit v1.2.3 From 445c6e0512acac0280f7c34ee756c51ed5b099cd Mon Sep 17 00:00:00 2001 From: Rezwanul Kabir Date: Wed, 23 Jun 2010 12:02:43 -0500 Subject: dell-laptop: Add another Dell laptop family to the DMI whitelist commit 410d44c74cf9942e3055d5b7d73953fac8efbacb upstream. This is to support Precision M4500 and others. Signed-off-by: Rezwanul Kabir Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/platform/x86/dell-laptop.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 61106019214d..0fb56e044f6c 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -82,6 +82,12 @@ static const struct dmi_system_id __initdata dell_device_table[] = { DMI_MATCH(DMI_CHASSIS_TYPE, "8"), }, }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /*Laptop*/ + }, + }, { .ident = "Dell Computer Corporation", .matches = { @@ -628,4 +634,5 @@ MODULE_AUTHOR("Matthew Garrett "); MODULE_DESCRIPTION("Dell laptop driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("dmi:*svnDellInc.:*:ct8:*"); +MODULE_ALIAS("dmi:*svnDellInc.:*:ct9:*"); MODULE_ALIAS("dmi:*svnDellComputerCorporation.:*:ct8:*"); -- cgit v1.2.3 From c5e74595507c13d213d716475d9c9fa061cd263c Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Dec 2010 14:55:03 +0000 Subject: btrfs: Require CAP_SYS_ADMIN for filesystem rebalance commit 6f88a4403def422bd8e276ddf6863d6ac71435d2 upstream. Filesystem rebalancing (BTRFS_IOC_BALANCE) affects the entire filesystem and may run uninterruptibly for a long time. This does not seem to be something that an unprivileged user should be able to do. Reported-by: Aron Xu Signed-off-by: Ben Hutchings Signed-off-by: Chris Mason Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/btrfs/volumes.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index d6e3af8be95b..dc0dedfa8e0c 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "compat.h" #include "ctree.h" @@ -1909,6 +1910,9 @@ int btrfs_balance(struct btrfs_root *dev_root) if (dev_root->fs_info->sb->s_flags & MS_RDONLY) return -EROFS; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + mutex_lock(&dev_root->fs_info->volume_mutex); dev_root = dev_root->fs_info->dev_root; -- cgit v1.2.3 From b930a41af4954ca009974a46fb7c91a8f974750d Mon Sep 17 00:00:00 2001 From: "Edgar (gimli) Hucek" Date: Thu, 11 Nov 2010 14:05:30 -0800 Subject: backlight: MacBookAir3,1(3,2) mbp-nvidia-bl support commit bd760e1e5b34351e0705705e5163cb89c1316d71 upstream. Add support for the MacBookAir3,1 and MacBookAir3,2 to the mbp-nvidia-bl driver. Signed-off-by: Edgar (gimli) Hucek Acked-by: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/video/backlight/mbp_nvidia_bl.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c index 9fb533f6373e..1485f7345f49 100644 --- a/drivers/video/backlight/mbp_nvidia_bl.c +++ b/drivers/video/backlight/mbp_nvidia_bl.c @@ -335,6 +335,24 @@ static const struct dmi_system_id __initdata mbp_device_table[] = { }, .driver_data = (void *)&nvidia_chipset_data, }, + { + .callback = mbp_dmi_match, + .ident = "MacBookAir 3,1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir3,1"), + }, + .driver_data = (void *)&nvidia_chipset_data, + }, + { + .callback = mbp_dmi_match, + .ident = "MacBookAir 3,2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir3,2"), + }, + .driver_data = (void *)&nvidia_chipset_data, + }, { } }; -- cgit v1.2.3 From d6864e9351e5031d5d98a47983f8846ade515082 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 20 Jan 2011 09:02:31 +0000 Subject: bonding: Ensure that we unshare skbs prior to calling pskb_may_pull commit b30532515f0a62bfe17207ab00883dd262497006 upstream. Recently reported oops: kernel BUG at net/core/skbuff.c:813! invalid opcode: 0000 [#1] SMP last sysfs file: /sys/devices/virtual/net/bond0/broadcast CPU 8 Modules linked in: sit tunnel4 cpufreq_ondemand acpi_cpufreq freq_table bonding ipv6 dm_mirror dm_region_hash dm_log cdc_ether usbnet mii serio_raw i2c_i801 i2c_core iTCO_wdt iTCO_vendor_support shpchp ioatdma i7core_edac edac_core bnx2 ixgbe dca mdio sg ext4 mbcache jbd2 sd_mod crc_t10dif mptsas mptscsih mptbase scsi_transport_sas dm_mod [last unloaded: microcode] Modules linked in: sit tunnel4 cpufreq_ondemand acpi_cpufreq freq_table bonding ipv6 dm_mirror dm_region_hash dm_log cdc_ether usbnet mii serio_raw i2c_i801 i2c_core iTCO_wdt iTCO_vendor_support shpchp ioatdma i7core_edac edac_core bnx2 ixgbe dca mdio sg ext4 mbcache jbd2 sd_mod crc_t10dif mptsas mptscsih mptbase scsi_transport_sas dm_mod [last unloaded: microcode] Pid: 0, comm: swapper Not tainted 2.6.32-71.el6.x86_64 #1 BladeCenter HS22 -[7870AC1]- RIP: 0010:[] [] pskb_expand_head+0x36/0x1e0 RSP: 0018:ffff880028303b70 EFLAGS: 00010202 RAX: 0000000000000002 RBX: ffff880c6458ec80 RCX: 0000000000000020 RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff880c6458ec80 RBP: ffff880028303bc0 R08: ffffffff818a6180 R09: ffff880c6458ed64 R10: ffff880c622b36c0 R11: 0000000000000400 R12: 0000000000000000 R13: 0000000000000180 R14: ffff880c622b3000 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff880028300000(0000) knlGS:0000000000000000 CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b CR2: 00000038653452a4 CR3: 0000000001001000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process swapper (pid: 0, threadinfo ffff8806649c2000, task ffff880c64f16ab0) Stack: ffff880028303bc0 ffffffff8104fff9 000000000000001c 0000000100000000 <0> ffff880000047d80 ffff880c6458ec80 000000000000001c ffff880c6223da00 <0> ffff880c622b3000 0000000000000000 ffff880028303c10 ffffffff81407f7a Call Trace: [] ? __wake_up_common+0x59/0x90 [] __pskb_pull_tail+0x2aa/0x360 [] bond_arp_rcv+0x2c0/0x2e0 [bonding] [] ? packet_rcv+0x377/0x440 [] netif_receive_skb+0x2db/0x670 [] napi_skb_finish+0x58/0x70 [] napi_gro_receive+0x39/0x50 [] ixgbe_clean_rx_irq+0x35b/0x900 [ixgbe] [] ixgbe_clean_rxtx_many+0x136/0x240 [ixgbe] [] net_rx_action+0x103/0x210 [] __do_softirq+0xb7/0x1e0 [] ? handle_IRQ_event+0x60/0x170 [] call_softirq+0x1c/0x30 [] do_softirq+0x65/0xa0 [] irq_exit+0x85/0x90 [] do_IRQ+0x75/0xf0 [] ret_from_intr+0x0/0x11 [] ? mwait_idle+0x71/0xd0 [] ? atomic_notifier_call_chain+0x1a/0x20 [] cpu_idle+0xb6/0x110 [] start_secondary+0x1fc/0x23f Resulted from bonding driver registering packet handlers via dev_add_pack and then trying to call pskb_may_pull. If another packet handler (like for AF_PACKET sockets) gets called first, the delivered skb will have a user count > 1, which causes pskb_may_pull to BUG halt when it does its skb_shared check. Fix this by calling skb_share_check prior to the may_pull call sites in the bonding driver to clone the skb when needed. Tested by myself and the reported successfully. Signed-off-by: Neil Horman Signed-off-by: Andi Kleen CC: Andy Gospodarek CC: Jay Vosburgh CC: "David S. Miller" Signed-off-by: Jay Vosburgh Signed-off-by: Andy Gospodarek Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/bonding/bond_3ad.c | 4 ++++ drivers/net/bonding/bond_alb.c | 4 ++++ drivers/net/bonding/bond_main.c | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 0ddf4c66afe2..9a002f1c0130 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2466,6 +2466,10 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac if (!(dev->flags & IFF_MASTER)) goto out; + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) + goto out; + if (!pskb_may_pull(skb, sizeof(struct lacpdu))) goto out; diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 0cb1ded1bf89..fc8575a9c798 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -369,6 +369,10 @@ static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct goto out; } + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) + goto out; + if (!pskb_may_pull(skb, arp_hdr_len(bond_dev))) goto out; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index c3d98dde2f86..a917230b518c 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2686,6 +2686,10 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack if (!slave || !slave_do_arp_validate(bond, slave)) goto out_unlock; + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) + goto out_unlock; + if (!pskb_may_pull(skb, arp_hdr_len(dev))) goto out_unlock; -- cgit v1.2.3 From 7b4fd0fff48eb5cd76bcf05e181e5f5187e77722 Mon Sep 17 00:00:00 2001 From: "Edgar (gimli) Hucek" Date: Wed, 3 Nov 2010 10:36:18 -0400 Subject: HID: add MacBookAir 3,1 and 3,2 support commit 99b9f758bbc904f22faffcf4d83205f4a5e7bc0c upstream. This patch add support for the MacBookAir3,1 and MacBookAir3,2 to the hid driver. Signed-off-by: Edgar (gimli) Hucek Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/hid/hid-apple.c | 46 ++++++++++++++++++++++++++++++++++++++++++---- drivers/hid/hid-core.c | 12 ++++++++++++ drivers/hid/hid-ids.h | 6 ++++++ 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index bba05d0a8980..1a2bb2add898 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -59,6 +59,27 @@ struct apple_key_translation { u8 flags; }; +static const struct apple_key_translation macbookair_fn_keys[] = { + { KEY_BACKSPACE, KEY_DELETE }, + { KEY_ENTER, KEY_INSERT }, + { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, + { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, + { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY }, + { KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY }, + { KEY_F6, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY }, + { KEY_F7, KEY_PLAYPAUSE, APPLE_FLAG_FKEY }, + { KEY_F8, KEY_NEXTSONG, APPLE_FLAG_FKEY }, + { KEY_F9, KEY_MUTE, APPLE_FLAG_FKEY }, + { KEY_F10, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY }, + { KEY_F11, KEY_VOLUMEUP, APPLE_FLAG_FKEY }, + { KEY_F12, KEY_EJECTCD, APPLE_FLAG_FKEY }, + { KEY_UP, KEY_PAGEUP }, + { KEY_DOWN, KEY_PAGEDOWN }, + { KEY_LEFT, KEY_HOME }, + { KEY_RIGHT, KEY_END }, + { } +}; + static const struct apple_key_translation apple_fn_keys[] = { { KEY_BACKSPACE, KEY_DELETE }, { KEY_ENTER, KEY_INSERT }, @@ -157,10 +178,15 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, if (fnmode) { int do_translate; - trans = apple_find_translation((hid->product < 0x21d || - hid->product >= 0x300) ? - powerbook_fn_keys : apple_fn_keys, - usage->code); + if(hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && + hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) { + trans = apple_find_translation(macbookair_fn_keys, usage->code); + } else if (hid->product < 0x21d || hid->product >= 0x300) { + trans = apple_find_translation(powerbook_fn_keys, usage->code); + } else { + trans = apple_find_translation(apple_fn_keys, usage->code); + } + if (trans) { if (test_bit(usage->code, asc->pressed_fn)) do_translate = 1; @@ -439,6 +465,18 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI), + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO), + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI), + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO), + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 866e54ec5fb2..1c3e12e48d82 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1275,6 +1275,12 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, @@ -1735,6 +1741,12 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { } diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 31601eef25dd..afbbb8fd32d4 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -93,6 +93,12 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 +#define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI 0x023f +#define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO 0x0240 +#define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS 0x0241 +#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 +#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 +#define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b -- cgit v1.2.3 From 879ed2486c8465ab8bd7b1bfd6f901e5589dbc16 Mon Sep 17 00:00:00 2001 From: Romain Francoise Date: Mon, 17 Jan 2011 07:59:18 +0000 Subject: ipv6: Silence privacy extensions initialization commit 2fdc1c8093255f9da877d7b9ce3f46c2098377dc upstream. When a network namespace is created (via CLONE_NEWNET), the loopback interface is automatically added to the new namespace, triggering a printk in ipv6_add_dev() if CONFIG_IPV6_PRIVACY is set. This is problematic for applications which use CLONE_NEWNET as part of a sandbox, like Chromium's suid sandbox or recent versions of vsftpd. On a busy machine, it can lead to thousands of useless "lo: Disabled Privacy Extensions" messages appearing in dmesg. It's easy enough to check the status of privacy extensions via the use_tempaddr sysctl, so just removing the printk seems like the most sensible solution. Signed-off-by: Romain Francoise Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ipv6/addrconf.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 0bbaddc32935..b5ab939d4d92 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -415,9 +415,6 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) dev->type == ARPHRD_TUNNEL6 || dev->type == ARPHRD_SIT || dev->type == ARPHRD_NONE) { - printk(KERN_INFO - "%s: Disabled Privacy Extensions\n", - dev->name); ndev->cnf.use_tempaddr = -1; } else { in6_dev_hold(ndev); -- cgit v1.2.3 From 04c735c129a5a86c6edd61743b4fb8fc6cbecfa7 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 2 Sep 2010 23:22:23 +0200 Subject: MIPS: DMA: Fix computation of DMA flags from device's coherent_dma_mask. commit 3b9c6c11f519718d618f5d7c9508daf78b207f6f upstream. This only matters for ISA devices with a 24-bit DMA limit or for devices with a 32-bit DMA limit on systems with ZONE_DMA32 enabled. The latter currently only affects 32-bit PCI cards on Sibyte-based systems with more than 1GB RAM installed. Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/mips/mm/dma-default.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 9547bc0cf188..b38ab4d3807b 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -44,27 +44,39 @@ static inline int cpu_is_noncoherent_r10000(struct device *dev) static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp) { + gfp_t dma_flag; + /* ignore region specifiers */ gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM); -#ifdef CONFIG_ZONE_DMA +#ifdef CONFIG_ISA if (dev == NULL) - gfp |= __GFP_DMA; - else if (dev->coherent_dma_mask < DMA_BIT_MASK(24)) - gfp |= __GFP_DMA; + dma_flag = __GFP_DMA; else #endif -#ifdef CONFIG_ZONE_DMA32 +#if defined(CONFIG_ZONE_DMA32) && defined(CONFIG_ZONE_DMA) if (dev->coherent_dma_mask < DMA_BIT_MASK(32)) - gfp |= __GFP_DMA32; + dma_flag = __GFP_DMA; + else if (dev->coherent_dma_mask < DMA_BIT_MASK(64)) + dma_flag = __GFP_DMA32; + else +#endif +#if defined(CONFIG_ZONE_DMA32) && !defined(CONFIG_ZONE_DMA) + if (dev->coherent_dma_mask < DMA_BIT_MASK(64)) + dma_flag = __GFP_DMA32; + else +#endif +#if defined(CONFIG_ZONE_DMA) && !defined(CONFIG_ZONE_DMA32) + if (dev->coherent_dma_mask < DMA_BIT_MASK(64)) + dma_flag = __GFP_DMA; else #endif - ; + dma_flag = 0; /* Don't invoke OOM killer */ gfp |= __GFP_NORETRY; - return gfp; + return gfp | dma_flag; } void *dma_alloc_noncoherent(struct device *dev, size_t size, -- cgit v1.2.3 From 6f40d761f0210858e4adbadd33b55020d291ef76 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 7 Sep 2010 04:35:19 +0000 Subject: niu: Fix kernel buffer overflow for ETHTOOL_GRXCLSRLALL commit ee9c5cfad29c8a13199962614b9b16f1c4137ac9 upstream. niu_get_ethtool_tcam_all() assumes that its output buffer is the right size, and warns before returning if it is not. However, the output buffer size is under user control and ETHTOOL_GRXCLSRLALL is an unprivileged ethtool command. Therefore this is at least a local denial-of-service vulnerability. Change it to check before writing each entry and to return an error if the buffer is already full. Compile-tested only. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller Signed-off-by: Andi Kleen [Adjusted to apply to 2.6.32 by dann frazier ] Signed-off-by: Greg Kroah-Hartman --- drivers/net/niu.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 63e8e3893bd6..1351cd5ca982 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -7270,32 +7270,28 @@ static int niu_get_ethtool_tcam_all(struct niu *np, struct niu_parent *parent = np->parent; struct niu_tcam_entry *tp; int i, idx, cnt; - u16 n_entries; unsigned long flags; - + int ret = 0; /* put the tcam size here */ nfc->data = tcam_get_size(np); niu_lock_parent(np, flags); - n_entries = nfc->rule_cnt; for (cnt = 0, i = 0; i < nfc->data; i++) { idx = tcam_get_index(np, i); tp = &parent->tcam[idx]; if (!tp->valid) continue; + if (cnt == nfc->rule_cnt) { + ret = -EMSGSIZE; + break; + } rule_locs[cnt] = i; cnt++; } niu_unlock_parent(np, flags); - if (n_entries != cnt) { - /* print warning, this should not happen */ - netdev_info(np->dev, "niu%d: In %s(): n_entries[%d] != cnt[%d]!!!\n", - np->parent->index, __func__, n_entries, cnt); - } - - return 0; + return ret; } static int niu_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd, -- cgit v1.2.3 From d58f50ab3cb89696982deeae32ef9e0eab96f787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Mon, 25 Oct 2010 10:43:32 +0300 Subject: Phonet: device notifier only runs on initial namespace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [bwh: This is only applicable to 2.6.32. Phonet was fixed upstream to work with multiple net namespaces.] This should really fix the OOPS when doing: unshare(CLONE_NEWNET); exit(0); while the phonet module is loaded. Signed-off-by: Rémi Denis-Courmont Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/phonet/pn_dev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index c33da6576942..29ae2bd677ce 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -298,6 +298,9 @@ static int phonet_device_notify(struct notifier_block *me, unsigned long what, { struct net_device *dev = arg; + if (!net_eq(dev_net(dev), &init_net)) + return 0; + switch (what) { case NETDEV_REGISTER: if (dev->type == ARPHRD_PHONET) -- cgit v1.2.3 From b234a8154e569f4cf63320e3acb5fee737a34b71 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 8 Jan 2011 14:24:01 +0000 Subject: powerpc/boot/dts: Install dts from the right directory commit 4d9ef89dee13e964ea8b064d82ff55cf36209237 upstream. The dts-installed variable is initialised using a wildcard path that will be expanded relative to the build directory. Use the existing variable dtstree to generate an absolute wildcard path that will work when building in a separate directory. Reported-by: Gerhard Pircher Signed-off-by: Ben Hutchings Tested-by: Gerhard Pircher [against 2.6.32] Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/powerpc/boot/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index fae8192c8fcc..2d8a80b5e641 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -370,7 +370,7 @@ INSTALL := install extra-installed := $(patsubst $(obj)/%, $(DESTDIR)$(WRAPPER_OBJDIR)/%, $(extra-y)) hostprogs-installed := $(patsubst %, $(DESTDIR)$(WRAPPER_BINDIR)/%, $(hostprogs-y)) wrapper-installed := $(DESTDIR)$(WRAPPER_BINDIR)/wrapper -dts-installed := $(patsubst $(obj)/dts/%, $(DESTDIR)$(WRAPPER_DTSDIR)/%, $(wildcard $(obj)/dts/*.dts)) +dts-installed := $(patsubst $(dtstree)/%, $(DESTDIR)$(WRAPPER_DTSDIR)/%, $(wildcard $(dtstree)/*.dts)) all-installed := $(extra-installed) $(hostprogs-installed) $(wrapper-installed) $(dts-installed) -- cgit v1.2.3 From 15d611d312597932f012f923a98871e7d1ba576c Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Wed, 23 Jun 2010 12:57:15 +0200 Subject: rt2500usb: fallback to SW encryption for TKIP+AES commit 75f64dd54a185150ebfc45e99351c890d4a2252f upstream. HW crypto in rt2500usb does not seem to support keys with different ciphers, which breaks TKIP+AES mode. Fall back to software encryption to fix it. This should fix long-standing problems with rt2500usb and WPA, such as: http://rt2x00.serialmonkey.com/phpBB/viewtopic.php?f=4&t=4834 https://bugzilla.redhat.com/show_bug.cgi?id=484888 Also tested that it does not break WEP, TKIP-only and AES-only modes. Signed-off-by: Ondrej Zary Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville Signed-off-by: Andi Kleen [bwh: Adjust context for 2.6.32] Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2500usb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 9e8b33d6d266..ae6118d1a649 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -348,6 +348,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, int timeout; u32 mask; u16 reg; + enum cipher curr_cipher; if (crypto->cmd == SET_KEY) { /* @@ -358,6 +359,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, mask = TXRX_CSR0_KEY_ID.bit_mask; rt2500usb_register_read(rt2x00dev, TXRX_CSR0, ®); + curr_cipher = rt2x00_get_field16(reg, TXRX_CSR0_ALGORITHM); reg &= mask; if (reg && reg == mask) @@ -366,6 +368,14 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID); key->hw_key_idx += reg ? ffz(reg) : 0; + /* + * Hardware requires that all keys use the same cipher + * (e.g. TKIP-only, AES-only, but not TKIP+AES). + * If this is not the first key, compare the cipher with the + * first one and fall back to SW crypto if not the same. + */ + if (key->hw_key_idx > 0 && crypto->cipher != curr_cipher) + return -EOPNOTSUPP; /* * The encryption key doesn't fit within the CSR cache, -- cgit v1.2.3 From 2f557bafe399f7e4c70e985eb1a864fabcd74c75 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 20 Jan 2011 13:59:06 +0100 Subject: libata: set queue DMA alignment to sector size for ATAPI too commit 729a6a300e628a48cf12bac93a964a535e83cd1d upstream. ata_pio_sectors() expects buffer for each sector to be contained in a single page; otherwise, it ends up overrunning the first page. This is achieved by setting queue DMA alignment. If sector_size is smaller than PAGE_SIZE and all buffers are sector_size aligned, buffer for each sector is always contained in a single page. This wasn't applied to ATAPI devices but IDENTIFY_PACKET is executed as ATA_PROT_PIO and thus uses ata_pio_sectors(). Newer versions of udev issue IDENTIFY_PACKET with unaligned buffer triggering the problem and causing oops. This patch fixes the problem by setting sdev->sector_size to ATA_SECT_SIZE on ATATPI devices and always setting DMA alignment to sector_size. While at it, add a warning for the unlikely but still possible scenario where sector_size is larger than PAGE_SIZE, in which case the alignment wouldn't be enough. Signed-off-by: Tejun Heo Reported-by: John Stanley Tested-by: John Stanley Signed-off-by: Jeff Garzik Signed-off-by: Jonathan Liu Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/ata/libata-scsi.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index fb9e3eea020e..ca972bc3e3c7 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1129,13 +1129,13 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, /* configure max sectors */ blk_queue_max_hw_sectors(sdev->request_queue, dev->max_sectors); + sdev->sector_size = ATA_SECT_SIZE; + if (dev->class == ATA_DEV_ATAPI) { struct request_queue *q = sdev->request_queue; void *buf; - /* set the min alignment and padding */ - blk_queue_update_dma_alignment(sdev->request_queue, - ATA_DMA_PAD_SZ - 1); + /* set DMA padding */ blk_queue_update_dma_pad(sdev->request_queue, ATA_DMA_PAD_SZ - 1); @@ -1149,12 +1149,24 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN); } else { - /* ATA devices must be sector aligned */ - blk_queue_update_dma_alignment(sdev->request_queue, - ATA_SECT_SIZE - 1); sdev->manage_start_stop = 1; } + /* + * ata_pio_sectors() expects buffer for each sector to not cross + * page boundary. Enforce it by requiring buffers to be sector + * aligned, which works iff sector_size is not larger than + * PAGE_SIZE. ATAPI devices also need the alignment as + * IDENTIFY_PACKET is executed as ATA_PROT_PIO. + */ + if (sdev->sector_size > PAGE_SIZE) + ata_dev_printk(dev, KERN_WARNING, + "sector_size=%u > PAGE_SIZE, PIO may malfunction\n", + sdev->sector_size); + + blk_queue_update_dma_alignment(sdev->request_queue, + sdev->sector_size - 1); + if (dev->flags & ATA_DFLAG_AN) set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events); -- cgit v1.2.3 From c966ef96919386c22f9491272473efbc671b38fb Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Feb 2011 10:36:53 +0200 Subject: usb: musb: core: set has_tt flag commit ec95d35a6bd0047f05fe8a21e6c52f8bb418da55 upstream. MUSB is a non-standard host implementation which can handle all speeds with the same core. We need to set has_tt flag after commit d199c96d41d80a567493e12b8e96ea056a1350c1 (USB: prevent buggy hubs from crashing the USB stack) in order for MUSB HCD to continue working. Signed-off-by: Felipe Balbi Cc: Alan Stern Tested-by: Michael Jones Tested-by: Alexander Holler Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/musb/musb_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 6128e7c200ff..006eaac791f4 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1868,6 +1868,7 @@ allocate_instance(struct device *dev, INIT_LIST_HEAD(&musb->out_bulk); hcd->uses_new_polling = 1; + hcd->has_tt = 1; musb->vbuserr_retry = VBUSERR_RETRY_COUNT; musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON; -- cgit v1.2.3 From da4e8b8ed55d397cfca5fa4656e7e71e7ba3d688 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Wed, 20 Apr 2011 01:57:15 +0000 Subject: can: add missing socket check in can/raw release commit 10022a6c66e199d8f61d9044543f38785713cbbd upstream. v2: added space after 'if' according code style. We can get here with a NULL socket argument passed from userspace, so we need to handle it accordingly. Thanks to Dave Jones pointing at this issue in net/can/bcm.c Signed-off-by: Oliver Hartkopp Signed-off-by: David S. Miller Cc: Chuck Ebbert Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/can/raw.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/can/raw.c b/net/can/raw.c index 1650599f995f..9ae3b9b23856 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -281,7 +281,12 @@ static int raw_init(struct sock *sk) static int raw_release(struct socket *sock) { struct sock *sk = sock->sk; - struct raw_sock *ro = raw_sk(sk); + struct raw_sock *ro; + + if (!sk) + return 0; + + ro = raw_sk(sk); unregister_netdevice_notifier(&ro->notifier); -- cgit v1.2.3 From 9f6340c7bfc445ec0c8c620d79a4cea4a8fe654d Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 1 May 2011 09:42:07 -0500 Subject: fix oops in scsi_run_queue() commit c055f5b2614b4f758ae6cc86733f31fa4c2c5844 upstream. The recent commit closing the race window in device teardown: commit 86cbfb5607d4b81b1a993ff689bbd2addd5d3a9b Author: James Bottomley Date: Fri Apr 22 10:39:59 2011 -0500 [SCSI] put stricter guards on queue dead checks is causing a potential NULL deref in scsi_run_queue() because the q->queuedata may already be NULL by the time this function is called. Since we shouldn't be running a queue that is being torn down, simply add a NULL check in scsi_run_queue() to forestall this. Tested-by: Jim Schutt Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/scsi/scsi_lib.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index c2a9e12fa6e1..725f3cdcedcf 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -400,10 +400,15 @@ static inline int scsi_host_is_busy(struct Scsi_Host *shost) static void scsi_run_queue(struct request_queue *q) { struct scsi_device *sdev = q->queuedata; - struct Scsi_Host *shost = sdev->host; + struct Scsi_Host *shost; LIST_HEAD(starved_list); unsigned long flags; + /* if the device is dead, sdev will be NULL, so no queue to run */ + if (!sdev) + return; + + shost = sdev->host; if (scsi_target(sdev)->single_lun) scsi_single_lun_run(sdev); -- cgit v1.2.3 From 43a36aea9fdbae025023cc500a74d498f380ec87 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 27 Apr 2011 13:25:51 -0400 Subject: cifs: check for bytes_remaining going to zero in CIFS_SessSetup commit fcda7f4578bbf9717444ca6da8a421d21489d078 upstream. It's possible that when we go to decode the string area in the SESSION_SETUP response, that bytes_remaining will be 0. Decrementing it at that point will mean that it can go "negative" and wrap. Check for a bytes_remaining value of 0, and don't try to decode the string area if that's the case. Reported-and-Acked-by: David Howells Signed-off-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/cifs/sess.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 0a57cb7db5dd..42873c14dd91 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -913,7 +913,9 @@ ssetup_ntlmssp_authenticate: } /* BB check if Unicode and decode strings */ - if (smb_buf->Flags2 & SMBFLG2_UNICODE) { + if (bytes_remaining == 0) { + /* no string area to decode, do nothing */ + } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) { /* unicode string area must be word-aligned */ if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { ++bcc_ptr; -- cgit v1.2.3 From 9f5a8a5d1018c56e5d74db644d739e1be72e6f88 Mon Sep 17 00:00:00 2001 From: Timo Warns Date: Fri, 6 May 2011 13:47:35 +0200 Subject: Validate size of EFI GUID partition entries. commit fa039d5f6b126fbd65eefa05db2f67e44df8f121 upstream. Otherwise corrupted EFI partition tables can cause total confusion. Signed-off-by: Timo Warns Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/partitions/efi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c index 9efb2cfe2410..3e0ee124a1b3 100644 --- a/fs/partitions/efi.c +++ b/fs/partitions/efi.c @@ -347,6 +347,12 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, goto fail; } + /* Check that sizeof_partition_entry has the correct value */ + if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) { + pr_debug("GUID Partitition Entry Size check failed.\n"); + goto fail; + } + if (!(*ptes = alloc_read_gpt_entries(state, *gpt))) goto fail; -- cgit v1.2.3 From 92f9dab23e4e424f28c6aca43cd2611b0b301965 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Fri, 6 May 2011 03:27:18 +0000 Subject: dccp: handle invalid feature options length commit a294865978b701e4d0d90135672749531b9a900d upstream. A length of zero (after subtracting two for the type and len fields) for the DCCPO_{CHANGE,CONFIRM}_{L,R} options will cause an underflow due to the subtraction. The subsequent code may read past the end of the options value buffer when parsing. I'm unsure of what the consequences of this might be, but it's probably not good. Signed-off-by: Dan Rosenberg Acked-by: Gerrit Renker Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/dccp/options.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/dccp/options.c b/net/dccp/options.c index 07395f861d35..92a41300a7f7 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -131,6 +131,8 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R: if (pkt_type == DCCP_PKT_DATA) /* RFC 4340, 6 */ break; + if (len == 0) + goto out_invalid_option; rc = dccp_feat_parse_options(sk, dreq, mandatory, opt, *value, value + 1, len - 1); if (rc) -- cgit v1.2.3 From f3b60ef4bcc7b233a816df5fded90e1ba99d47d6 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Thu, 14 Apr 2011 22:00:56 +0400 Subject: CIFS: Fix memory over bound bug in cifs_parse_mount_options commit 4906e50b37e6f6c264e7ee4237343eb2b7f8d16d upstream. While password processing we can get out of options array bound if the next character after array is delimiter. The patch adds a check if we reach the end. Signed-off-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/cifs/connect.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 50d60cc80ce8..a30b080490ed 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -801,8 +801,7 @@ static int cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol) { - char *value; - char *data; + char *value, *data, *end; unsigned int temp_len, i, j; char separator[2]; short int override_uid = -1; @@ -845,6 +844,7 @@ cifs_parse_mount_options(char *options, const char *devname, if (!options) return 1; + end = options + strlen(options); if (strncmp(options, "sep=", 4) == 0) { if (options[4] != 0) { separator[0] = options[4]; @@ -909,6 +909,7 @@ cifs_parse_mount_options(char *options, const char *devname, the only illegal character in a password is null */ if ((value[temp_len] == 0) && + (value + temp_len < end) && (value[temp_len+1] == separator[0])) { /* reinsert comma */ value[temp_len] = separator[0]; -- cgit v1.2.3 From 63fa187cc0f6c581f69ee056e8b2b043d6f84ce5 Mon Sep 17 00:00:00 2001 From: Kleber Sacilotto de Souza Date: Wed, 4 May 2011 13:05:11 +0000 Subject: ehea: fix wrongly reported speed and port commit dcbe14b91a920657ff3a9ba0efb7c5b5562f956a upstream. Currently EHEA reports to ethtool as supporting 10M, 100M, 1G and 10G and connected to FIBRE independent of the hardware configuration. However, when connected to FIBRE the only supported speed is 10G full-duplex, and the other speeds and modes are only supported when connected to twisted pair. Signed-off-by: Kleber Sacilotto de Souza Acked-by: Breno Leitao Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/ehea/ehea_ethtool.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/net/ehea/ehea_ethtool.c b/drivers/net/ehea/ehea_ethtool.c index 75b099ce49c9..f97da2a8896f 100644 --- a/drivers/net/ehea/ehea_ethtool.c +++ b/drivers/net/ehea/ehea_ethtool.c @@ -53,15 +53,20 @@ static int ehea_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->duplex = -1; } - cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_1000baseT_Full - | SUPPORTED_100baseT_Full | SUPPORTED_100baseT_Half - | SUPPORTED_10baseT_Full | SUPPORTED_10baseT_Half - | SUPPORTED_Autoneg | SUPPORTED_FIBRE); - - cmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_Autoneg - | ADVERTISED_FIBRE); + if (cmd->speed == SPEED_10000) { + cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); + cmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); + cmd->port = PORT_FIBRE; + } else { + cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full + | SUPPORTED_100baseT_Half | SUPPORTED_10baseT_Full + | SUPPORTED_10baseT_Half | SUPPORTED_Autoneg + | SUPPORTED_TP); + cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg + | ADVERTISED_TP); + cmd->port = PORT_TP; + } - cmd->port = PORT_FIBRE; cmd->autoneg = port->autoneg == 1 ? AUTONEG_ENABLE : AUTONEG_DISABLE; return 0; -- cgit v1.2.3 From 8eca68a77b9403beca2abebee81737c3fe423407 Mon Sep 17 00:00:00 2001 From: Matvejchikov Ilya Date: Fri, 6 May 2011 06:23:09 +0000 Subject: NET: slip, fix ldisc->open retval commit 057bef938896e6266ae24ec4266d24792d27c29a upstream. TTY layer expects 0 if the ldisc->open operation succeeded. Signed-off-by : Matvejchikov Ilya Acked-by: Oliver Hartkopp Acked-by: Alan Cox Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/slip.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/slip.c b/drivers/net/slip.c index fa434fb8fb7c..fff62f477214 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -852,7 +852,9 @@ static int slip_open(struct tty_struct *tty) /* Done. We have linked the TTY line to a channel. */ rtnl_unlock(); tty->receive_room = 65536; /* We don't flow control */ - return sl->dev->base_addr; + + /* TTY layer expects 0 on success */ + return 0; err_free_bufs: sl_free_bufs(sl); -- cgit v1.2.3 From f6f5ac3edfdc5b1f5595d0216b1ac6cc5448024c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 12 May 2011 09:11:40 +0000 Subject: ne-h8300: Fix regression caused during net_device_ops conversion commit 2592a7354092afd304a8c067319b15ab1e441e35 upstream. Changeset dcd39c90290297f6e6ed8a04bb20da7ac2b043c5 ("ne-h8300: convert to net_device_ops") broke ne-h8300 by adding 8390.o to the link. That meant that lib8390.c was included twice, once in ne-h8300.c and once in 8390.c, subject to different macros. This patch reverts that by avoiding the wrappers in 8390.c. Fix based on commits 217cbfa856dc1cbc2890781626c4032d9e3ec59f ("mac8390: fix regression caused during net_device_ops conversion") and 4e0168fa4842e27795a75b205a510f25b62181d9 ("mac8390: fix build with NET_POLL_CONTROLLER"). Signed-off-by: Geert Uytterhoeven Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/Makefile | 2 +- drivers/net/ne-h8300.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 0a0512ae77da..3051870fda71 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -141,7 +141,7 @@ obj-$(CONFIG_NE3210) += ne3210.o 8390.o obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o obj-$(CONFIG_B44) += b44.o obj-$(CONFIG_FORCEDETH) += forcedeth.o -obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o +obj-$(CONFIG_NE_H8300) += ne-h8300.o obj-$(CONFIG_AX88796) += ax88796.o obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c index e0b0ef11f110..f15fbeb2d2bd 100644 --- a/drivers/net/ne-h8300.c +++ b/drivers/net/ne-h8300.c @@ -167,7 +167,7 @@ static void cleanup_card(struct net_device *dev) #ifndef MODULE struct net_device * __init ne_probe(int unit) { - struct net_device *dev = alloc_ei_netdev(); + struct net_device *dev = ____alloc_ei_netdev(0); int err; if (!dev) @@ -197,15 +197,15 @@ static const struct net_device_ops ne_netdev_ops = { .ndo_open = ne_open, .ndo_stop = ne_close, - .ndo_start_xmit = ei_start_xmit, - .ndo_tx_timeout = ei_tx_timeout, - .ndo_get_stats = ei_get_stats, - .ndo_set_multicast_list = ei_set_multicast_list, + .ndo_start_xmit = __ei_start_xmit, + .ndo_tx_timeout = __ei_tx_timeout, + .ndo_get_stats = __ei_get_stats, + .ndo_set_multicast_list = __ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = ei_poll, + .ndo_poll_controller = __ei_poll, #endif }; @@ -637,7 +637,7 @@ int init_module(void) int err; for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { - struct net_device *dev = alloc_ei_netdev(); + struct net_device *dev = ____alloc_ei_netdev(0); if (!dev) break; if (io[this_dev]) { -- cgit v1.2.3 From 02b5e373b2f4a28762cb6ff908b9b726bb17c844 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 12 May 2011 09:11:39 +0000 Subject: hydra: Fix regression caused during net_device_ops conversion commit 0b25e0157dfa236a0629c16c8ad6f222f633f682 upstream. Changeset 5618f0d1193d6b051da9b59b0e32ad24397f06a4 ("hydra: convert to net_device_ops") broke hydra by adding 8390.o to the link. That meant that lib8390.c was included twice, once in hydra.c and once in 8390.c, subject to different macros. This patch reverts that by avoiding the wrappers in 8390.c. Fix based on commits 217cbfa856dc1cbc2890781626c4032d9e3ec59f ("mac8390: fix regression caused during net_device_ops conversion") and 4e0168fa4842e27795a75b205a510f25b62181d9 ("mac8390: fix build with NET_POLL_CONTROLLER"). Signed-off-by: Geert Uytterhoeven Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/Makefile | 2 +- drivers/net/hydra.c | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 3051870fda71..9c89b50e1f26 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -225,7 +225,7 @@ obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o obj-$(CONFIG_DECLANCE) += declance.o obj-$(CONFIG_ATARILANCE) += atarilance.o obj-$(CONFIG_A2065) += a2065.o -obj-$(CONFIG_HYDRA) += hydra.o 8390.o +obj-$(CONFIG_HYDRA) += hydra.o obj-$(CONFIG_ARIADNE) += ariadne.o obj-$(CONFIG_CS89x0) += cs89x0.o obj-$(CONFIG_MACSONIC) += macsonic.o diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index 07d8e5b634f3..828c750443a6 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c @@ -98,15 +98,15 @@ static const struct net_device_ops hydra_netdev_ops = { .ndo_open = hydra_open, .ndo_stop = hydra_close, - .ndo_start_xmit = ei_start_xmit, - .ndo_tx_timeout = ei_tx_timeout, - .ndo_get_stats = ei_get_stats, - .ndo_set_multicast_list = ei_set_multicast_list, + .ndo_start_xmit = __ei_start_xmit, + .ndo_tx_timeout = __ei_tx_timeout, + .ndo_get_stats = __ei_get_stats, + .ndo_set_multicast_list = __ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = ei_poll, + .ndo_poll_controller = __ei_poll, #endif }; @@ -125,7 +125,7 @@ static int __devinit hydra_init(struct zorro_dev *z) 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, }; - dev = alloc_ei_netdev(); + dev = ____alloc_ei_netdev(0); if (!dev) return -ENOMEM; -- cgit v1.2.3 From 57ad6fccb924ec7fdb6aa88aa41ebc76da76fa74 Mon Sep 17 00:00:00 2001 From: Paul Fox Date: Mon, 9 May 2011 10:40:42 +0100 Subject: libertas: fix cmdpendingq locking commit 2ae1b8b35faba31a59b153cbad07f9c15de99740 upstream. We occasionally see list corruption using libertas. While we haven't been able to diagnose this precisely, we have spotted a possible cause: cmdpendingq is generally modified with driver_lock held. However, there are a couple of points where this is not the case. Fix up those operations to execute under the lock, it seems like the correct thing to do and will hopefully improve the situation. Signed-off-by: Paul Fox Signed-off-by: Daniel Drake Acked-by: Dan Williams Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/libertas/cmd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index cdb9b9650d73..91bafae4fda5 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1267,8 +1267,8 @@ int lbs_execute_next_command(struct lbs_private *priv) cpu_to_le16(CMD_SUBCMD_EXIT_PS)) { lbs_deb_host( "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n"); - list_del(&cmdnode->list); spin_lock_irqsave(&priv->driver_lock, flags); + list_del(&cmdnode->list); lbs_complete_command(priv, cmdnode, 0); spin_unlock_irqrestore(&priv->driver_lock, flags); @@ -1280,8 +1280,8 @@ int lbs_execute_next_command(struct lbs_private *priv) (priv->psstate == PS_STATE_PRE_SLEEP)) { lbs_deb_host( "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n"); - list_del(&cmdnode->list); spin_lock_irqsave(&priv->driver_lock, flags); + list_del(&cmdnode->list); lbs_complete_command(priv, cmdnode, 0); spin_unlock_irqrestore(&priv->driver_lock, flags); priv->needtowakeup = 1; @@ -1294,7 +1294,9 @@ int lbs_execute_next_command(struct lbs_private *priv) "EXEC_NEXT_CMD: sending EXIT_PS\n"); } } + spin_lock_irqsave(&priv->driver_lock, flags); list_del(&cmdnode->list); + spin_unlock_irqrestore(&priv->driver_lock, flags); lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n", le16_to_cpu(cmd->command)); lbs_submit_command(priv, cmdnode); -- cgit v1.2.3 From 2dcdb613c69f16e6c22b05010a92c104b8a8deee Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 12 May 2011 09:11:38 +0000 Subject: zorro8390: Fix regression caused during net_device_ops conversion commit cf7e032fc87d59c475df26c4d40bf45d401b2adb upstream. Changeset b6114794a1c394534659f4a17420e48cf23aa922 ("zorro8390: convert to net_device_ops") broke zorro8390 by adding 8390.o to the link. That meant that lib8390.c was included twice, once in zorro8390.c and once in 8390.c, subject to different macros. This patch reverts that by avoiding the wrappers in 8390.c. Fix based on commits 217cbfa856dc1cbc2890781626c4032d9e3ec59f ("mac8390: fix regression caused during net_device_ops conversion") and 4e0168fa4842e27795a75b205a510f25b62181d9 ("mac8390: fix build with NET_POLL_CONTROLLER"). Reported-by: Christian T. Steigies Suggested-by: Finn Thain Signed-off-by: Geert Uytterhoeven Tested-by: Christian T. Steigies Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/Makefile | 2 +- drivers/net/zorro8390.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 9c89b50e1f26..3c58a7a971f8 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -213,7 +213,7 @@ obj-$(CONFIG_SC92031) += sc92031.o obj-$(CONFIG_LP486E) += lp486e.o obj-$(CONFIG_ETH16I) += eth16i.o -obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o +obj-$(CONFIG_ZORRO8390) += zorro8390.o obj-$(CONFIG_HPLANCE) += hplance.o 7990.o obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o obj-$(CONFIG_EQUALIZER) += eql.o diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c index b78a38d9172a..8c7c522a056a 100644 --- a/drivers/net/zorro8390.c +++ b/drivers/net/zorro8390.c @@ -126,7 +126,7 @@ static int __devinit zorro8390_init_one(struct zorro_dev *z, board = z->resource.start; ioaddr = board+cards[i].offset; - dev = alloc_ei_netdev(); + dev = ____alloc_ei_netdev(0); if (!dev) return -ENOMEM; if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, DRV_NAME)) { @@ -146,15 +146,15 @@ static int __devinit zorro8390_init_one(struct zorro_dev *z, static const struct net_device_ops zorro8390_netdev_ops = { .ndo_open = zorro8390_open, .ndo_stop = zorro8390_close, - .ndo_start_xmit = ei_start_xmit, - .ndo_tx_timeout = ei_tx_timeout, - .ndo_get_stats = ei_get_stats, - .ndo_set_multicast_list = ei_set_multicast_list, + .ndo_start_xmit = __ei_start_xmit, + .ndo_tx_timeout = __ei_tx_timeout, + .ndo_get_stats = __ei_get_stats, + .ndo_set_multicast_list = __ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = ei_poll, + .ndo_poll_controller = __ei_poll, #endif }; -- cgit v1.2.3 From e68fd06bd319088e3fbeb40be74cdd444242cfd6 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 17 May 2011 06:40:30 -0400 Subject: cifs: add fallback in is_path_accessible for old servers commit 221d1d797202984cb874e3ed9f1388593d34ee22 upstream. The is_path_accessible check uses a QPathInfo call, which isn't supported by ancient win9x era servers. Fall back to an older SMBQueryInfo call if it fails with the magic error codes. Reported-and-Tested-by: Sandro Bonazzola Signed-off-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/cifs/connect.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index a30b080490ed..79168612049a 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2423,6 +2423,11 @@ is_path_accessible(int xid, struct cifsTconInfo *tcon, 0 /* not legacy */, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + + if (rc == -EOPNOTSUPP || rc == -EINVAL) + rc = SMBQueryInformation(xid, tcon, full_path, pfile_info, + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); kfree(pfile_info); return rc; } -- cgit v1.2.3 From b9c582a117a0d590b7a174760b662d25761692d4 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 17 May 2011 14:55:19 +0200 Subject: x86, AMD: Fix ARAT feature setting again commit 14fb57dccb6e1defe9f89a66f548fcb24c374c1d upstream. Trying to enable the local APIC timer on early K8 revisions uncovers a number of other issues with it, in conjunction with the C1E enter path on AMD. Fixing those causes much more churn and troubles than the benefit of using that timer brings so don't enable it on K8 at all, falling back to the original functionality the kernel had wrt to that. Reported-and-bisected-by: Nick Bowler Cc: Boris Ostrovsky Cc: Andreas Herrmann Cc: Greg Kroah-Hartman Cc: Hans Rosenfeld Cc: Nick Bowler Cc: Joerg-Volker-Peetz Signed-off-by: Borislav Petkov Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/1305636919-31165-3-git-send-email-bp@amd64.org Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/amd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index b203d0dbfc04..38254806bf31 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -566,7 +566,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) #endif /* As a rule processors have APIC timer running in deep C states */ - if (c->x86 >= 0xf && !cpu_has_amd_erratum(amd_erratum_400)) + if (c->x86 > 0xf && !cpu_has_amd_erratum(amd_erratum_400)) set_cpu_cap(c, X86_FEATURE_ARAT); /* -- cgit v1.2.3 From 5284561b0290f09e1c6c99a18b4bc6f39b5ca4d1 Mon Sep 17 00:00:00 2001 From: john stultz Date: Wed, 4 May 2011 18:16:50 -0700 Subject: clocksource: Install completely before selecting commit e05b2efb82596905ebfe88e8612ee81dec9b6592 upstream. Christian Hoffmann reported that the command line clocksource override with acpi_pm timer fails: Kernel command line: clocksource=acpi_pm hpet clockevent registered Switching to clocksource hpet Override clocksource acpi_pm is not HRT compatible. Cannot switch while in HRT/NOHZ mode. The watchdog code is what enables CLOCK_SOURCE_VALID_FOR_HRES, but we actually end up selecting the clocksource before we enqueue it into the watchdog list, so that's why we see the warning and fail to switch to acpi_pm timer as requested. That's particularly bad when we want to debug timekeeping related problems in early boot. Put the selection call last. Reported-by: Christian Hoffmann Signed-off-by: John Stultz Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/%3C1304558210.2943.24.camel%40work-vm%3E Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/time/clocksource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index f08e99c1d561..c232eebbf7ee 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -665,8 +665,8 @@ int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq) mutex_lock(&clocksource_mutex); clocksource_enqueue(cs); - clocksource_select(); clocksource_enqueue_watchdog(cs); + clocksource_select(); mutex_unlock(&clocksource_mutex); return 0; } -- cgit v1.2.3 From 3b4e9894a65820b8b3588199a54dfde64e705bfb Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 16 May 2011 11:07:48 +0200 Subject: tick: Clear broadcast active bit when switching to oneshot commit 07f4beb0b5bbfaf36a64aa00d59e670ec578a95a upstream. The first cpu which switches from periodic to oneshot mode switches also the broadcast device into oneshot mode. The broadcast device serves as a backup for per cpu timers which stop in deeper C-states. To avoid starvation of the cpus which might be in idle and depend on broadcast mode it marks the other cpus as broadcast active and sets the brodcast expiry value of those cpus to the next tick. The oneshot mode broadcast bit for the other cpus is sticky and gets only cleared when those cpus exit idle. If a cpu was not idle while the bit got set in consequence the bit prevents that the broadcast device is armed on behalf of that cpu when it enters idle for the first time after it switched to oneshot mode. In most cases that goes unnoticed as one of the other cpus has usually a timer pending which keeps the broadcast device armed with a short timeout. Now if the only cpu which has a short timer active has the bit set then the broadcast device will not be armed on behalf of that cpu and will fire way after the expected timer expiry. In the case of Christians bug report it took ~145 seconds which is about half of the wrap around time of HPET (the limit for that device) due to the fact that all other cpus had no timers armed which expired before the 145 seconds timeframe. The solution is simply to clear the broadcast active bit unconditionally when a cpu switches to oneshot mode after the first cpu switched the broadcast device over. It's not idle at that point otherwise it would not be executing that code. [ I fundamentally hate that broadcast crap. Why the heck thought some folks that when going into deep idle it's a brilliant concept to switch off the last device which brings the cpu back from that state? ] Thanks to Christian for providing all the valuable debug information! Reported-and-tested-by: Christian Hoffmann Cc: John Stultz Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/%3Calpine.LFD.2.02.1105161105170.3078%40ionos%3E Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/time/tick-broadcast.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 2030f62d689e..0f888cb837cc 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -523,10 +523,11 @@ static void tick_broadcast_init_next_event(struct cpumask *mask, */ void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { + int cpu = smp_processor_id(); + /* Set it up only once ! */ if (bc->event_handler != tick_handle_oneshot_broadcast) { int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC; - int cpu = smp_processor_id(); bc->event_handler = tick_handle_oneshot_broadcast; clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT); @@ -552,6 +553,15 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc) tick_broadcast_set_event(tick_next_period, 1); } else bc->next_event.tv64 = KTIME_MAX; + } else { + /* + * The first cpu which switches to oneshot mode sets + * the bit for all other cpus which are in the general + * (periodic) broadcast mask. So the bit is set and + * would prevent the first broadcast enter after this + * to program the bc device. + */ + tick_broadcast_clear_oneshot(cpu); } } -- cgit v1.2.3 From 532c8c080814b714c2becae8f877b28c0fcf06f6 Mon Sep 17 00:00:00 2001 From: Youquan Song Date: Fri, 22 Apr 2011 00:22:43 +0800 Subject: x86, apic: Fix spurious error interrupts triggering on all non-boot APs commit e503f9e4b092e2349a9477a333543de8f3c7f5d9 upstream. This patch fixes a bug reported by a customer, who found that many unreasonable error interrupts reported on all non-boot CPUs (APs) during the system boot stage. According to Chapter 10 of Intel Software Developer Manual Volume 3A, Local APIC may signal an illegal vector error when an LVT entry is set as an illegal vector value (0~15) under FIXED delivery mode (bits 8-11 is 0), regardless of whether the mask bit is set or an interrupt actually happen. These errors are seen as error interrupts. The initial value of thermal LVT entries on all APs always reads 0x10000 because APs are woken up by BSP issuing INIT-SIPI-SIPI sequence to them and LVT registers are reset to 0s except for the mask bits which are set to 1s when APs receive INIT IPI. When the BIOS takes over the thermal throttling interrupt, the LVT thermal deliver mode should be SMI and it is required from the kernel to keep AP's LVT thermal monitoring register programmed as such as well. This issue happens when BIOS does not take over thermal throttling interrupt, AP's LVT thermal monitor register will be restored to 0x10000 which means vector 0 and fixed deliver mode, so all APs will signal illegal vector error interrupts. This patch check if interrupt delivery mode is not fixed mode before restoring AP's LVT thermal monitor register. Signed-off-by: Youquan Song Acked-by: Suresh Siddha Acked-by: Yong Wang Cc: hpa@linux.intel.com Cc: joe@perches.com Cc: jbaron@redhat.com Cc: trenn@suse.de Cc: kent.liu@intel.com Cc: chaohong.guo@intel.com Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/1303402963-17738-1-git-send-email-youquan.song@intel.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/apicdef.h | 1 + arch/x86/kernel/cpu/mcheck/therm_throt.c | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h index 7fe3b3060f08..49d7c96791dc 100644 --- a/arch/x86/include/asm/apicdef.h +++ b/arch/x86/include/asm/apicdef.h @@ -78,6 +78,7 @@ #define APIC_DEST_LOGICAL 0x00800 #define APIC_DEST_PHYSICAL 0x00000 #define APIC_DM_FIXED 0x00000 +#define APIC_DM_FIXED_MASK 0x00700 #define APIC_DM_LOWEST 0x00100 #define APIC_DM_SMI 0x00200 #define APIC_DM_REMRD 0x00300 diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index e1a0a3bf9716..22100c649e74 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -293,18 +293,20 @@ void intel_init_thermal(struct cpuinfo_x86 *c) */ rdmsr(MSR_IA32_MISC_ENABLE, l, h); + h = lvtthmr_init; /* * The initial value of thermal LVT entries on all APs always reads * 0x10000 because APs are woken up by BSP issuing INIT-SIPI-SIPI * sequence to them and LVT registers are reset to 0s except for * the mask bits which are set to 1s when APs receive INIT IPI. - * Always restore the value that BIOS has programmed on AP based on - * BSP's info we saved since BIOS is always setting the same value - * for all threads/cores + * If BIOS takes over the thermal interrupt and sets its interrupt + * delivery mode to SMI (not fixed), it restores the value that the + * BIOS has programmed on AP based on BSP's info we saved since BIOS + * is always setting the same value for all threads/cores. */ - apic_write(APIC_LVTTHMR, lvtthmr_init); + if ((h & APIC_DM_FIXED_MASK) != APIC_DM_FIXED) + apic_write(APIC_LVTTHMR, lvtthmr_init); - h = lvtthmr_init; if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) { printk(KERN_DEBUG -- cgit v1.2.3 From 1528a22557dde6a0d5aaf7a174a09c45fc3f968f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 13 May 2011 15:52:09 +0200 Subject: x86, mce, AMD: Fix leaving freed data in a list commit d9a5ac9ef306eb5cc874f285185a15c303c50009 upstream. b may be added to a list, but is not removed before being freed in the case of an error. This is done in the corresponding deallocation function, so the code here has been changed to follow that. The sematic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression E,E1,E2; identifier l; @@ *list_add(&E->l,E1); ... when != E1 when != list_del(&E->l) when != list_del_init(&E->l) when != E = E2 *kfree(E);// Signed-off-by: Julia Lawall Cc: Borislav Petkov Cc: Robert Richter Cc: Yinghai Lu Cc: Andreas Herrmann Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/1305294731-12127-1-git-send-email-julia@diku.dk Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mcheck/mce_amd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index f80ff85d1ef9..1bdce3410b5e 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -469,6 +469,7 @@ recurse: out_free: if (b) { kobject_put(&b->kobj); + list_del(&b->miscj); kfree(b); } return err; -- cgit v1.2.3 From 6451865d838216814412405879b6906271b50199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 19 Jan 2011 10:01:14 +0100 Subject: megaraid_sas: Sanity check user supplied length before passing it to dma_alloc_coherent() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 98cb7e4413d189cd2b54daf993a4667d9788c0bb upstream. The ioc->sgl[i].iov_len value is supplied by the ioctl caller, and can be zero in some cases. Assume that's valid and continue without error. Fixes (multiple individual reports of the same problem for quite a while): http://marc.info/?l=linux-ide&m=128941801715301 http://bugs.debian.org/604627 http://www.mail-archive.com/linux-poweredge@dell.com/msg02575.html megasas: Failed to alloc kernel SGL buffer for IOCTL and [ 69.162538] ------------[ cut here ]------------ [ 69.162806] kernel BUG at /build/buildd/linux-2.6.32/lib/swiotlb.c:368! [ 69.163134] invalid opcode: 0000 [#1] SMP [ 69.163570] last sysfs file: /sys/devices/system/cpu/cpu3/cache/index2/shared_cpu_map [ 69.163975] CPU 0 [ 69.164227] Modules linked in: fbcon tileblit font bitblit softcursor vga16fb vgastate ioatdma radeon ttm drm_kms_helper shpchp drm i2c_algo_bit lp parport floppy pata_jmicron megaraid_sas igb dca [ 69.167419] Pid: 1206, comm: smartctl Tainted: G W 2.6.32-25-server #45-Ubuntu X8DTN [ 69.167843] RIP: 0010:[] [] map_single+0x255/0x260 [ 69.168370] RSP: 0018:ffff88081c0ebc58 EFLAGS: 00010246 [ 69.168655] RAX: 000000000003bffc RBX: 00000000ffffffff RCX: 0000000000000002 [ 69.169000] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88001dffe000 [ 69.169346] RBP: ffff88081c0ebcb8 R08: 0000000000000000 R09: ffff880000030840 [ 69.169691] R10: 0000000000100000 R11: 0000000000000000 R12: 0000000000000000 [ 69.170036] R13: 00000000ffffffff R14: 0000000000000001 R15: 0000000000200000 [ 69.170382] FS: 00007fb8de189720(0000) GS:ffff88001de00000(0000) knlGS:0000000000000000 [ 69.170794] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 69.171094] CR2: 00007fb8dd59237c CR3: 000000081a790000 CR4: 00000000000006f0 [ 69.171439] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 69.171784] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 69.172130] Process smartctl (pid: 1206, threadinfo ffff88081c0ea000, task ffff88081a760000) [ 69.194513] Stack: [ 69.205788] 0000000000000034 00000002817e3390 0000000000000000 ffff88081c0ebe00 [ 69.217739] <0> 0000000000000000 000000000003bffc 0000000000000000 0000000000000000 [ 69.241250] <0> 0000000000000000 00000000ffffffff ffff88081c5b4080 ffff88081c0ebe00 [ 69.277310] Call Trace: [ 69.289278] [] swiotlb_alloc_coherent+0xec/0x130 [ 69.301118] [] x86_swiotlb_alloc_coherent+0x61/0x70 [ 69.313045] [] megasas_mgmt_fw_ioctl+0x1ae/0x690 [megaraid_sas] [ 69.336399] [] megasas_mgmt_ioctl_fw+0x198/0x240 [megaraid_sas] [ 69.359346] [] megasas_mgmt_ioctl+0x35/0x50 [megaraid_sas] [ 69.370902] [] vfs_ioctl+0x22/0xa0 [ 69.382322] [] ? alloc_fd+0x10a/0x150 [ 69.393622] [] do_vfs_ioctl+0x81/0x410 [ 69.404696] [] ? do_page_fault+0x153/0x3b0 [ 69.415761] [] sys_ioctl+0x81/0xa0 [ 69.426640] [] system_call_fastpath+0x16/0x1b [ 69.437491] Code: fe ff ff 48 8b 3d 74 38 76 00 41 bf 00 00 20 00 e8 51 f5 d7 ff 83 e0 ff 48 05 ff 07 00 00 48 c1 e8 0b 48 89 45 c8 e9 13 fe ff ff <0f> 0b eb fe 0f 1f 80 00 00 00 00 55 48 89 e5 48 83 ec 20 4c 89 [ 69.478216] RIP [] map_single+0x255/0x260 [ 69.489668] RSP [ 69.500975] ---[ end trace 6a2181b634e2abc7 ]--- Reported-by: Bokhan Artem Signed-off-by: Andi Kleen Reported by: Marc-Christian Petersen Signed-off-by: Bjørn Mork Cc: Michael Benz Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/megaraid/megaraid_sas.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 99e4478c3f3e..1d2e162baecb 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -3669,6 +3669,9 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, * For each user buffer, create a mirror buffer and copy in */ for (i = 0; i < ioc->sge_count; i++) { + if (!ioc->sgl[i].iov_len) + continue; + kbuff_arr[i] = dma_alloc_coherent(&instance->pdev->dev, ioc->sgl[i].iov_len, &buf_handle, GFP_KERNEL); -- cgit v1.2.3 From 728b8bcaf8c31db1af214c999b38672b4144cf96 Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Mon, 16 May 2011 06:28:15 +0000 Subject: vmxnet3: Fix inconsistent LRO state after initialization commit ebde6f8acba92abfc203585198a54f47e83e2cd0 upstream. During initialization of vmxnet3, the state of LRO gets out of sync with netdev->features. This leads to very poor TCP performance in a IP forwarding setup and is hitting many VMware users. Simplified call sequence: 1. vmxnet3_declare_features() initializes "adapter->lro" to true. 2. The kernel automatically disables LRO if IP forwarding is enabled, so vmxnet3_set_flags() gets called. This also updates netdev->features. 3. Now vmxnet3_setup_driver_shared() is called. "adapter->lro" is still set to true and LRO gets enabled again, even though netdev->features shows it's disabled. Fix it by updating "adapter->lro", too. The private vmxnet3 adapter flags are scheduled for removal in net-next, see commit a0d2730c9571aeba793cb5d3009094ee1d8fda35 "net: vmxnet3: convert to hw_features". Patch applies to 2.6.37 / 2.6.38 and 2.6.39-rc6. Please CC: comments. Signed-off-by: Thomas Jarosch Acked-by: Stephen Hemminger Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/vmxnet3/vmxnet3_ethtool.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c index 3935c4493fb7..df7cddd0c2b5 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethtool.c +++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c @@ -290,6 +290,9 @@ vmxnet3_set_flags(struct net_device *netdev, u32 data) { /* toggle the LRO feature*/ netdev->features ^= NETIF_F_LRO; + /* Update private LRO flag */ + adapter->lro = lro_requested; + /* update harware LRO capability accordingly */ if (lro_requested) adapter->shared->devRead.misc.uptFeatures &= UPT1_F_LRO; -- cgit v1.2.3 From 297cd2138dad33c4bec7902e833a637351232422 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 17 May 2011 01:48:14 +0100 Subject: netxen: Remove references to unified firmware file Commit c23a103f0d9c2560c6839ed366feebec4cd5e556 wrongly introduced references to the unified firmware file "phanfw.bin", which is not supported by netxen in 2.6.32. The driver reports this filename when loading firmware from flash, and includes a MODULE_FIRMWARE hint for the filename even though it will never use it. Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/netxen/netxen_nic.h | 1 - drivers/net/netxen/netxen_nic_init.c | 1 - drivers/net/netxen/netxen_nic_main.c | 1 - 3 files changed, 3 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index ffa1b9ce1cc5..e883d4c65d30 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -522,7 +522,6 @@ struct uni_data_desc{ #define NX_P2_MN_ROMIMAGE_NAME "nxromimg.bin" #define NX_P3_CT_ROMIMAGE_NAME "nx3fwct.bin" #define NX_P3_MN_ROMIMAGE_NAME "nx3fwmn.bin" -#define NX_UNIFIED_ROMIMAGE_NAME "phanfw.bin" #define NX_FLASH_ROMIMAGE_NAME "flash" extern char netxen_nic_driver_name[]; diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 81f982aa334c..211799740291 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -971,7 +971,6 @@ static char *fw_name[] = { NX_P2_MN_ROMIMAGE_NAME, NX_P3_CT_ROMIMAGE_NAME, NX_P3_MN_ROMIMAGE_NAME, - NX_UNIFIED_ROMIMAGE_NAME, NX_FLASH_ROMIMAGE_NAME, }; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 6ce6ce1df6d2..ca3bbd8a4382 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -44,7 +44,6 @@ MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID); MODULE_FIRMWARE(NX_P2_MN_ROMIMAGE_NAME); MODULE_FIRMWARE(NX_P3_CT_ROMIMAGE_NAME); MODULE_FIRMWARE(NX_P3_MN_ROMIMAGE_NAME); -MODULE_FIRMWARE(NX_UNIFIED_ROMIMAGE_NAME); char netxen_nic_driver_name[] = "netxen_nic"; static char netxen_nic_driver_string[] = "QLogic/NetXen Network Driver v" -- cgit v1.2.3 From 6ea4870f102c97460c57cc9ae32d8e17a277baef Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 29 Apr 2011 22:35:33 -0400 Subject: ftrace: Only update the function code on write to filter files commit 058e297d34a404caaa5ed277de15698d8dc43000 upstream. If function tracing is enabled, a read of the filter files will cause the call to stop_machine to update the function trace sites. It should only call stop_machine on write. Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/trace/ftrace.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index d9aaa9b786eb..f23b055e0d49 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -2377,14 +2377,16 @@ ftrace_regex_release(struct inode *inode, struct file *file, int enable) ftrace_match_records(parser->buffer, parser->idx, enable); } - mutex_lock(&ftrace_lock); - if (ftrace_start_up && ftrace_enabled) - ftrace_run_update_code(FTRACE_ENABLE_CALLS); - mutex_unlock(&ftrace_lock); - trace_parser_put(parser); kfree(iter); + if (file->f_mode & FMODE_WRITE) { + mutex_lock(&ftrace_lock); + if (ftrace_start_up && ftrace_enabled) + ftrace_run_update_code(FTRACE_ENABLE_CALLS); + mutex_unlock(&ftrace_lock); + } + mutex_unlock(&ftrace_regex_lock); return 0; } -- cgit v1.2.3 From 465e9df58b3007510231e030db6f622f4a46a6ac Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Wed, 27 Apr 2011 16:44:26 +0100 Subject: kmemleak: Do not return a pointer to an object that kmemleak did not get commit 52c3ce4ec5601ee383a14f1485f6bac7b278896e upstream. The kmemleak_seq_next() function tries to get an object (and increment its use count) before returning it. If it could not get the last object during list traversal (because it may have been freed), the function should return NULL rather than a pointer to such object that it did not get. Signed-off-by: Catalin Marinas Reported-by: Phil Carmody Acked-by: Phil Carmody Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- mm/kmemleak.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 2c0d032ac898..49c94b53a6c6 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -1368,9 +1368,12 @@ static void *kmemleak_seq_next(struct seq_file *seq, void *v, loff_t *pos) ++(*pos); list_for_each_continue_rcu(n, &object_list) { - next_obj = list_entry(n, struct kmemleak_object, object_list); - if (get_object(next_obj)) + struct kmemleak_object *obj = + list_entry(n, struct kmemleak_object, object_list); + if (get_object(obj)) { + next_obj = obj; break; + } } put_object(prev_obj); -- cgit v1.2.3 From f8c02e3305bdf8656219da21fde9f0b8b31c0508 Mon Sep 17 00:00:00 2001 From: Jacob Shin Date: Wed, 27 Apr 2011 13:32:11 -0500 Subject: CPU hotplug, re-create sysfs directory and symlinks commit 27ecddc2a9f99ce4ac9a59a0acd77f7100b6d034 upstream. When we discover CPUs that are affected by each other's frequency/voltage transitions, the first CPU gets a sysfs directory created, and rest of the siblings get symlinks. Currently, when we hotplug off only the first CPU, all of the symlinks and the sysfs directory gets removed. Even though rest of the siblings are still online and functional, they are orphaned, and no longer governed by cpufreq. This patch, given the above scenario, creates a sysfs directory for the first sibling and symlinks for the rest of the siblings. Please note the recursive call, it was rather too ugly to roll it out. And the removal of redundant NULL setting (it is already taken care of near the top of the function). Signed-off-by: Jacob Shin Acked-by: Mark Langsdorf Reviewed-by: Thomas Renninger Signed-off-by: Dave Jones Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/cpufreq/cpufreq.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 938b74ea9ffb..ecdc59b48ef6 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1205,12 +1205,28 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev) cpufreq_driver->exit(data); unlock_policy_rwsem_write(cpu); + cpufreq_debug_enable_ratelimit(); + +#ifdef CONFIG_HOTPLUG_CPU + /* when the CPU which is the parent of the kobj is hotplugged + * offline, check for siblings, and create cpufreq sysfs interface + * and symlinks + */ + if (unlikely(cpumask_weight(data->cpus) > 1)) { + /* first sibling now owns the new sysfs dir */ + cpumask_clear_cpu(cpu, data->cpus); + cpufreq_add_dev(get_cpu_sysdev(cpumask_first(data->cpus))); + + /* finally remove our own symlink */ + lock_policy_rwsem_write(cpu); + __cpufreq_remove_dev(sys_dev); + } +#endif + free_cpumask_var(data->related_cpus); free_cpumask_var(data->cpus); kfree(data); - per_cpu(cpufreq_cpu_data, cpu) = NULL; - cpufreq_debug_enable_ratelimit(); return 0; } -- cgit v1.2.3 From c4e60bd6930b93a13432f53dfb70e65d8fef58d2 Mon Sep 17 00:00:00 2001 From: steven finney Date: Mon, 2 May 2011 11:29:17 -0700 Subject: Fix memory leak in cpufreq_stat commit 98586ed8b8878e10691203687e89a42fa3355300 upstream. When a CPU is taken offline in an SMP system, cpufreq_remove_dev() nulls out the per-cpu policy before cpufreq_stats_free_table() can make use of it. cpufreq_stats_free_table() then skips the call to sysfs_remove_group(), leaving about 100 bytes of sysfs-related memory unclaimed each time a CPU-removal occurs. Break up cpu_stats_free_table into sysfs and table portions, and call the sysfs portion early. Signed-off-by: Steven Finney Signed-off-by: Dave Jones Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/cpufreq/cpufreq_stats.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 00d73fc8e4e2..4f1b8de2c9f3 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -165,17 +165,27 @@ static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq) return -1; } +/* should be called late in the CPU removal sequence so that the stats + * memory is still available in case someone tries to use it. + */ static void cpufreq_stats_free_table(unsigned int cpu) { struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu); - struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); - if (policy && policy->cpu == cpu) - sysfs_remove_group(&policy->kobj, &stats_attr_group); if (stat) { kfree(stat->time_in_state); kfree(stat); } per_cpu(cpufreq_stats_table, cpu) = NULL; +} + +/* must be called early in the CPU removal sequence (before + * cpufreq_remove_dev) so that policy is still valid. + */ +static void cpufreq_stats_free_sysfs(unsigned int cpu) +{ + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); + if (policy && policy->cpu == cpu) + sysfs_remove_group(&policy->kobj, &stats_attr_group); if (policy) cpufreq_cpu_put(policy); } @@ -316,6 +326,9 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb, case CPU_ONLINE_FROZEN: cpufreq_update_policy(cpu); break; + case CPU_DOWN_PREPARE: + cpufreq_stats_free_sysfs(cpu); + break; case CPU_DEAD: case CPU_DEAD_FROZEN: cpufreq_stats_free_table(cpu); @@ -324,9 +337,11 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } +/* priority=1 so this will get called before cpufreq_remove_dev */ static struct notifier_block cpufreq_stat_cpu_notifier __refdata = { .notifier_call = cpufreq_stat_cpu_callback, + .priority = 1, }; static struct notifier_block notifier_policy_block = { -- cgit v1.2.3 From 9c9f2de51e46be3011a100b4b401a6f17d220776 Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Tue, 10 May 2011 19:28:33 +0000 Subject: powerpc/kexec: Fix memory corruption from unallocated slaves commit 3d2cea732d68aa270c360f55d8669820ebce188a upstream. Commit 1fc711f7ffb01089efc58042cfdbac8573d1b59a (powerpc/kexec: Fix race in kexec shutdown) moved the write to signal the cpu had exited the kernel from before the transition to real mode in kexec_smp_wait to kexec_wait. Unfornately it missed that kexec_wait is used both by cpus leaving the kernel and by secondary slave cpus that were not allocated a paca for what ever reason -- they could be beyond nr_cpus or not described in the current device tree for whatever reason (for example, kexec-load was not refreshed after a cpu hotplug operation). Cpus coming through that path they will write to paca[NR_CPUS] which is beyond the space allocated for the paca data and overwrite memory not allocated to pacas but very likely still real mode accessable). Move the write back to kexec_smp_wait, which is used only by cpus that found their paca, but after the transition to real mode. Signed-off-by: Milton Miller Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/powerpc/kernel/misc_64.S | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index e5144906a56d..21eeb4c55b1d 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -461,7 +461,8 @@ _GLOBAL(disable_kernel_fp) * wait for the flag to change, indicating this kernel is going away but * the slave code for the next one is at addresses 0 to 100. * - * This is used by all slaves. + * This is used by all slaves, even those that did not find a matching + * paca in the secondary startup code. * * Physical (hardware) cpu id should be in r3. */ @@ -470,10 +471,6 @@ _GLOBAL(kexec_wait) 1: mflr r5 addi r5,r5,kexec_flag-1b - li r4,KEXEC_STATE_REAL_MODE - stb r4,PACAKEXECSTATE(r13) - SYNC - 99: HMT_LOW #ifdef CONFIG_KEXEC /* use no memory without kexec */ lwz r4,0(r5) @@ -498,11 +495,17 @@ kexec_flag: * * get phys id from paca * switch to real mode + * mark the paca as no longer used * join other cpus in kexec_wait(phys_id) */ _GLOBAL(kexec_smp_wait) lhz r3,PACAHWCPUID(r13) bl real_mode + + li r4,KEXEC_STATE_REAL_MODE + stb r4,PACAKEXECSTATE(r13) + SYNC + b .kexec_wait /* -- cgit v1.2.3 From 4ede8259d84a843e2adc0ce69523015608a5f271 Mon Sep 17 00:00:00 2001 From: Eric B Munson Date: Mon, 23 May 2011 04:22:40 +0000 Subject: powerpc/oprofile: Handle events that raise an exception without overflowing commit ad5d5292f16c6c1d7d3e257c4c7407594286b97e upstream. Commit 0837e3242c73566fc1c0196b4ec61779c25ffc93 fixes a situation on POWER7 where events can roll back if a specualtive event doesn't actually complete. This can raise a performance monitor exception. We need to catch this to ensure that we reset the PMC. In all cases the PMC will be less than 256 cycles from overflow. This patch lifts Anton's fix for the problem in perf and applies it to oprofile as well. Signed-off-by: Eric B Munson Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/powerpc/oprofile/op_model_power4.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index 80774092db77..93636ca48d3d 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c @@ -261,6 +261,28 @@ static int get_kernel(unsigned long pc, unsigned long mmcra) return is_kernel; } +static bool pmc_overflow(unsigned long val) +{ + if ((int)val < 0) + return true; + + /* + * Events on POWER7 can roll back if a speculative event doesn't + * eventually complete. Unfortunately in some rare cases they will + * raise a performance monitor exception. We need to catch this to + * ensure we reset the PMC. In all cases the PMC will be 256 or less + * cycles from overflow. + * + * We only do this if the first pass fails to find any overflowing + * PMCs because a user might set a period of less than 256 and we + * don't want to mistakenly reset them. + */ + if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256)) + return true; + + return false; +} + static void power4_handle_interrupt(struct pt_regs *regs, struct op_counter_config *ctr) { @@ -281,7 +303,7 @@ static void power4_handle_interrupt(struct pt_regs *regs, for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) { val = classic_ctr_read(i); - if (val < 0) { + if (pmc_overflow(val)) { if (oprofile_running && ctr[i].enabled) { oprofile_add_ext_sample(pc, regs, i, is_kernel); classic_ctr_write(i, reset_value[i]); -- cgit v1.2.3 From 0871ccb857a76c76be1e4c8b3d1dfdd7f3e91fe7 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 18 May 2011 16:20:10 +0200 Subject: block: add proper state guards to __elv_next_request commit 0a58e077eb600d1efd7e54ad9926a75a39d7f8ae upstream. blk_cleanup_queue() calls elevator_exit() and after this, we can't touch the elevator without oopsing. __elv_next_request() must check for this state because in the refcounted queue model, we can still call it after blk_cleanup_queue() has been called. This was reported as causing an oops attributable to scsi. Signed-off-by: James Bottomley Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- block/blk.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/block/blk.h b/block/blk.h index 5ee3d7e72feb..141483695145 100644 --- a/block/blk.h +++ b/block/blk.h @@ -62,7 +62,8 @@ static inline struct request *__elv_next_request(struct request_queue *q) return rq; } - if (!q->elevator->ops->elevator_dispatch_fn(q, 0)) + if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags) || + !q->elevator->ops->elevator_dispatch_fn(q, 0)) return NULL; } } -- cgit v1.2.3 From 4613fee87c204e79ebd9c1c269c53ee3c9204451 Mon Sep 17 00:00:00 2001 From: Felix Radensky Date: Mon, 25 Apr 2011 01:57:12 +0300 Subject: mtd: mtdconcat: fix NAND OOB write commit 431e1ecabddcd7cbba237182ddf431771f98bb4c upstream. Currently mtdconcat is broken for NAND. An attemtpt to create JFFS2 filesystem on concatenation of several NAND devices fails with OOB write errors. This patch fixes that problem. Signed-off-by: Felix Radensky Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/mtd/mtdconcat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index 7e075621bbf4..b356a0514101 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c @@ -305,7 +305,7 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) if (!(mtd->flags & MTD_WRITEABLE)) return -EROFS; - ops->retlen = 0; + ops->retlen = ops->oobretlen = 0; for (i = 0; i < concat->num_subdev; i++) { struct mtd_info *subdev = concat->subdev[i]; @@ -320,7 +320,7 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) devops.len = subdev->size - to; err = subdev->write_oob(subdev, to, &devops); - ops->retlen += devops.retlen; + ops->retlen += devops.oobretlen; if (err) return err; -- cgit v1.2.3 From b6403b5b5e39a36afb98dba3901844f34586b391 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 12 May 2011 16:30:30 +0200 Subject: x86, 64-bit: Fix copy_[to/from]_user() checks for the userspace address limit commit 26afb7c661080ae3f1f13ddf7f0c58c4f931c22b upstream. As reported in BZ #30352: https://bugzilla.kernel.org/show_bug.cgi?id=30352 there's a kernel bug related to reading the last allowed page on x86_64. The _copy_to_user() and _copy_from_user() functions use the following check for address limit: if (buf + size >= limit) fail(); while it should be more permissive: if (buf + size > limit) fail(); That's because the size represents the number of bytes being read/write from/to buf address AND including the buf address. So the copy function will actually never touch the limit address even if "buf + size == limit". Following program fails to use the last page as buffer due to the wrong limit check: #include #include #include #define PAGE_SIZE (4096) #define LAST_PAGE ((void*)(0x7fffffffe000)) int main() { int fds[2], err; void * ptr = mmap(LAST_PAGE, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); assert(ptr == LAST_PAGE); err = socketpair(AF_LOCAL, SOCK_STREAM, 0, fds); assert(err == 0); err = send(fds[0], ptr, PAGE_SIZE, 0); perror("send"); assert(err == PAGE_SIZE); err = recv(fds[1], ptr, PAGE_SIZE, MSG_WAITALL); perror("recv"); assert(err == PAGE_SIZE); return 0; } The other place checking the addr limit is the access_ok() function, which is working properly. There's just a misleading comment for the __range_not_ok() macro - which this patch fixes as well. The last page of the user-space address range is a guard page and Brian Gerst observed that the guard page itself due to an erratum on K8 cpus (#121 Sequential Execution Across Non-Canonical Boundary Causes Processor Hang). However, the test code is using the last valid page before the guard page. The bug is that the last byte before the guard page can't be read because of the off-by-one error. The guard page is left in place. This bug would normally not show up because the last page is part of the process stack and never accessed via syscalls. Signed-off-by: Jiri Olsa Acked-by: Brian Gerst Acked-by: Linus Torvalds Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/1305210630-7136-1-git-send-email-jolsa@redhat.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/uaccess.h | 2 +- arch/x86/lib/copy_user_64.S | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index abd3e0ea762a..99f0ad753f32 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -42,7 +42,7 @@ * Returns 0 if the range is valid, nonzero otherwise. * * This is equivalent to the following test: - * (u33)addr + (u33)size >= (u33)current->addr_limit.seg (u65 for x86_64) + * (u33)addr + (u33)size > (u33)current->addr_limit.seg (u65 for x86_64) * * This needs 33-bit (65-bit for x86_64) arithmetic. We have a carry... */ diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S index 71100c98e337..a4899ae3975f 100644 --- a/arch/x86/lib/copy_user_64.S +++ b/arch/x86/lib/copy_user_64.S @@ -72,7 +72,7 @@ ENTRY(_copy_to_user) addq %rdx,%rcx jc bad_to_user cmpq TI_addr_limit(%rax),%rcx - jae bad_to_user + ja bad_to_user ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string CFI_ENDPROC ENDPROC(_copy_to_user) @@ -85,7 +85,7 @@ ENTRY(_copy_from_user) addq %rdx,%rcx jc bad_from_user cmpq TI_addr_limit(%rax),%rcx - jae bad_from_user + ja bad_from_user ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string CFI_ENDPROC ENDPROC(_copy_from_user) -- cgit v1.2.3 From 94f69b03006a2119db2e7f1f6db453fe58e530b8 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 27 Apr 2011 18:20:44 +0200 Subject: ext3: Fix fs corruption when make_indexed_dir() fails commit 86c4f6d85595cd7da635dc6985d27bfa43b1ae10 upstream. When make_indexed_dir() fails (e.g. because of ENOSPC) after it has allocated block for index tree root, we did not properly mark all changed buffers dirty. This lead to only some of these buffers being written out and thus effectively corrupting the directory. Fix the issue by marking all changed data dirty even in the error failure case. Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ext3/namei.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 827b5736a4f8..7eecac016e3f 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -1425,10 +1425,19 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, frame->at = entries; frame->bh = bh; bh = bh2; + /* + * Mark buffers dirty here so that if do_split() fails we write a + * consistent set of buffers to disk. + */ + ext3_journal_dirty_metadata(handle, frame->bh); + ext3_journal_dirty_metadata(handle, bh); de = do_split(handle,dir, &bh, frame, &hinfo, &retval); - dx_release (frames); - if (!(de)) + if (!de) { + ext3_mark_inode_dirty(handle, dir); + dx_release(frames); return retval; + } + dx_release(frames); return add_dirent_to_buf(handle, dentry, inode, de, bh); } -- cgit v1.2.3 From 9907f140638ef8492c3ecd35db8d2f6b28f5c781 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 5 May 2011 13:59:35 +0200 Subject: jbd: Fix forever sleeping process in do_get_write_access() commit 2842bb20eed2e25cde5114298edc62c8883a1d9a upstream. In do_get_write_access() we wait on BH_Unshadow bit for buffer to get from shadow state. The waking code in journal_commit_transaction() has a bug because it does not issue a memory barrier after the buffer is moved from the shadow state and before wake_up_bit() is called. Thus a waitqueue check can happen before the buffer is actually moved from the shadow state and waiting process may never be woken. Fix the problem by issuing proper barrier. Reported-by: Tao Ma Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/jbd/commit.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 28a9ddaa0c49..bf21291e179a 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -745,8 +745,13 @@ wait_for_iobuf: required. */ JBUFFER_TRACE(jh, "file as BJ_Forget"); journal_file_buffer(jh, commit_transaction, BJ_Forget); - /* Wake up any transactions which were waiting for this - IO to complete */ + /* + * Wake up any transactions which were waiting for this + * IO to complete. The barrier must be here so that changes + * by journal_file_buffer() take effect before wake_up_bit() + * does the waitqueue check. + */ + smp_mb(); wake_up_bit(&bh->b_state, BH_Unshadow); JBUFFER_TRACE(jh, "brelse shadowed buffer"); __brelse(bh); -- cgit v1.2.3 From a33dc63a996b979dcdf1574752f67d1844aad91b Mon Sep 17 00:00:00 2001 From: Ted Ts'o Date: Sat, 30 Apr 2011 13:17:11 -0400 Subject: jbd: fix fsync() tid wraparound bug commit d9b01934d56a96d9f4ae2d6204d4ea78a36f5f36 upstream. If an application program does not make any changes to the indirect blocks or extent tree, i_datasync_tid will not get updated. If there are enough commits (i.e., 2**31) such that tid_geq()'s calculations wrap, and there isn't a currently active transaction at the time of the fdatasync() call, this can end up triggering a BUG_ON in fs/jbd/commit.c: J_ASSERT(journal->j_running_transaction != NULL); It's pretty rare that this can happen, since it requires the use of fdatasync() plus *very* frequent and excessive use of fsync(). But with the right workload, it can. We fix this by replacing the use of tid_geq() with an equality test, since there's only one valid transaction id that is valid for us to start: namely, the currently running transaction (if it exists). Reported-by: Martin_Zielinski@McAfee.com Signed-off-by: "Theodore Ts'o" Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/jbd/journal.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 93d1e47647bd..7a629b796e6f 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -435,9 +435,12 @@ int __log_space_left(journal_t *journal) int __log_start_commit(journal_t *journal, tid_t target) { /* - * Are we already doing a recent enough commit? + * The only transaction we can possibly wait upon is the + * currently running transaction (if it exists). Otherwise, + * the target tid must be an old one. */ - if (!tid_geq(journal->j_commit_request, target)) { + if (journal->j_running_transaction && + journal->j_running_transaction->t_tid == target) { /* * We want a new commit: OK, mark the request and wakup the * commit thread. We do _not_ do the commit ourselves. @@ -449,7 +452,14 @@ int __log_start_commit(journal_t *journal, tid_t target) journal->j_commit_sequence); wake_up(&journal->j_wait_commit); return 1; - } + } else if (!tid_geq(journal->j_commit_request, target)) + /* This should never happen, but if it does, preserve + the evidence before kjournald goes into a loop and + increments j_commit_sequence beyond all recognition. */ + WARN_ONCE(1, "jbd: bad log_start_commit: %u %u %u %u\n", + journal->j_commit_request, journal->j_commit_sequence, + target, journal->j_running_transaction ? + journal->j_running_transaction->t_tid : 0); return 0; } -- cgit v1.2.3 From 6d6bb6e9897f3c4443da0498e8d4622de85a26f2 Mon Sep 17 00:00:00 2001 From: Yang Ruirui Date: Sat, 16 Apr 2011 19:17:48 -0400 Subject: ext4: release page cache in ext4_mb_load_buddy error path commit 26626f1172fb4f3f323239a6a5cf4e082643fa46 upstream. Add missing page_cache_release in the error path of ext4_mb_load_buddy Signed-off-by: Yang Ruirui Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ext4/mballoc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 12b3bc026a68..994a719b995c 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -1175,6 +1175,8 @@ repeat_load_buddy: return 0; err: + if (page) + page_cache_release(page); if (e4b->bd_bitmap_page) page_cache_release(e4b->bd_bitmap_page); if (e4b->bd_buddy_page) -- cgit v1.2.3 From 7d5fdc4f5641f5e3046a4f4c614157b08e6ce53c Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Wed, 18 May 2011 17:06:05 +0200 Subject: Fix Ultrastor asm snippet commit fad4dab5e44e10acf6b0235e469cb8e773b58e31 upstream. Commit 1292500b replaced "=m" (*field) : "1" (*field) with "=m" (*field) : with comment "The following patch fixes it by using the '+' operator on the (*field) operand, marking it as read-write to gcc." '+' was actually forgotten. This really puts it. Signed-off-by: Samuel Thibault Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/scsi/ultrastor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c index 27aa40f3980e..7f0eda23e1ec 100644 --- a/drivers/scsi/ultrastor.c +++ b/drivers/scsi/ultrastor.c @@ -306,7 +306,7 @@ static inline int find_and_clear_bit_16(unsigned long *field) "0: bsfw %1,%w0\n\t" "btr %0,%1\n\t" "jnc 0b" - : "=&r" (rv), "=m" (*field) :); + : "=&r" (rv), "+m" (*field) :); return rv; } -- cgit v1.2.3 From 6dcd6090760630cfcc8016b1c0382c1c50d42810 Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Thu, 26 May 2011 11:19:52 -0400 Subject: x86, amd: Do not enable ARAT feature on AMD processors below family 0x12 commit e9cdd343a5e42c43bcda01e609fa23089e026470 upstream. Commit b87cf80af3ba4b4c008b4face3c68d604e1715c6 added support for ARAT (Always Running APIC timer) on AMD processors that are not affected by erratum 400. This erratum is present on certain processor families and prevents APIC timer from waking up the CPU when it is in a deep C state, including C1E state. Determining whether a processor is affected by this erratum may have some corner cases and handling these cases is somewhat complicated. In the interest of simplicity we won't claim ARAT support on processor families below 0x12 and will go back to broadcasting timer when going idle. Signed-off-by: Boris Ostrovsky Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/1306423192-19774-1-git-send-email-ostr@amd64.org Tested-by: Boris Petkov Cc: Hans Rosenfeld Cc: Andreas Herrmann Cc: Chuck Ebbert Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/amd.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 38254806bf31..ce87794943fa 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -565,8 +565,11 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) } #endif - /* As a rule processors have APIC timer running in deep C states */ - if (c->x86 > 0xf && !cpu_has_amd_erratum(amd_erratum_400)) + /* + * Family 0x12 and above processors have APIC timer + * running in deep C states. + */ + if (c->x86 > 0x11) set_cpu_cap(c, X86_FEATURE_ARAT); /* -- cgit v1.2.3 From b399e568ca3b163bdaeb121e0f3d735fb21d1f5b Mon Sep 17 00:00:00 2001 From: "Roedel, Joerg" Date: Thu, 19 May 2011 11:13:39 +0200 Subject: x86, amd: Use _safe() msr access for GartTlbWlk disable code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit d47cc0db8fd6011de2248df505fc34990b7451bf upstream. The workaround for Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=33012 introduced a read and a write to the MC4 mask msr. Unfortunatly this MSR is not emulated by the KVM hypervisor so that the kernel will get a #GP and crashes when applying this workaround when running inside KVM. This issue was reported as: https://bugzilla.kernel.org/show_bug.cgi?id=35132 and is fixed with this patch. The change just let the kernel ignore any #GP it gets while accessing this MSR by using the _safe msr access methods. Reported-by: Török Edwin Signed-off-by: Joerg Roedel Cc: Rafael J. Wysocki Cc: Maciej Rutecki Cc: Avi Kivity Cc: Andrew Morton Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/kernel/cpu/amd.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index ce87794943fa..29dfd22ab642 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -585,10 +585,13 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) * Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33012 */ u64 mask; + int err; - rdmsrl(MSR_AMD64_MCx_MASK(4), mask); - mask |= (1 << 10); - wrmsrl(MSR_AMD64_MCx_MASK(4), mask); + err = rdmsrl_safe(MSR_AMD64_MCx_MASK(4), &mask); + if (err == 0) { + mask |= (1 << 10); + checking_wrmsrl(MSR_AMD64_MCx_MASK(4), mask); + } } } -- cgit v1.2.3 From 738b2bfd83a0bc74f14ca52e7e0fc87be8996176 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Fri, 20 May 2011 02:09:54 +0200 Subject: rcu: Fix unpaired rcu_irq_enter() from locking selftests commit ba9f207c9f82115aba4ce04b22e0081af0ae300f upstream. HARDIRQ_ENTER() maps to irq_enter() which calls rcu_irq_enter(). But HARDIRQ_EXIT() maps to __irq_exit() which doesn't call rcu_irq_exit(). So for every locking selftest that simulates hardirq disabled, we create an imbalance in the rcu extended quiescent state internal state. As a result, after the first missing rcu_irq_exit(), subsequent irqs won't exit dyntick-idle mode after leaving the interrupt handler. This means that RCU won't see the affected CPU as being in an extended quiescent state, resulting in long grace-period delays (as in grace periods extending for hours). To fix this, just use __irq_enter() to simulate the hardirq context. This is sufficient for the locking selftests as we don't need to exit any extended quiescent state or perform any check that irqs normally do when they wake up from idle. As a side effect, this patch makes it possible to restore "rcu: Decrease memory-barrier usage based on semi-formal proof", which eventually helped finding this bug. Reported-and-tested-by: Yinghai Lu Signed-off-by: Frederic Weisbecker Cc: Paul E. McKenney Cc: Ingo Molnar Cc: Peter Zijlstra Signed-off-by: Paul E. McKenney Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- lib/locking-selftest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c index 619313ed6c46..507a22fab738 100644 --- a/lib/locking-selftest.c +++ b/lib/locking-selftest.c @@ -144,7 +144,7 @@ static void init_shared_classes(void) #define HARDIRQ_ENTER() \ local_irq_disable(); \ - irq_enter(); \ + __irq_enter(); \ WARN_ON(!in_irq()); #define HARDIRQ_EXIT() \ -- cgit v1.2.3 From c8648b4c2b720f21cba4040e47ce8dbc6e93ef8f Mon Sep 17 00:00:00 2001 From: David Chang Date: Thu, 12 May 2011 18:31:11 +0800 Subject: staging: usbip: fix wrong endian conversion commit cacd18a8476ce145ca5dcd46dc5b75585fd1289c upstream. Fix number_of_packets wrong endian conversion in function correct_endian_ret_submit() Signed-off-by: David Chang Acked-by: Arjan Mels Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/usbip/usbip_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c index c141eef47257..f4e3e11e0212 100644 --- a/drivers/staging/usbip/usbip_common.c +++ b/drivers/staging/usbip/usbip_common.c @@ -709,7 +709,7 @@ static void correct_endian_ret_submit(struct usbip_header_ret_submit *pdu, be32_to_cpus(&pdu->status); be32_to_cpus(&pdu->actual_length); be32_to_cpus(&pdu->start_frame); - cpu_to_be32s(&pdu->number_of_packets); + be32_to_cpus(&pdu->number_of_packets); be32_to_cpus(&pdu->error_count); } } -- cgit v1.2.3 From 60bdd71df9c36e1e1710155fded924e93347a9d2 Mon Sep 17 00:00:00 2001 From: Timo Warns Date: Thu, 19 May 2011 09:24:17 +0200 Subject: Fix for buffer overflow in ldm_frag_add not sufficient commit cae13fe4cc3f24820ffb990c09110626837e85d4 upstream. As Ben Hutchings discovered [1], the patch for CVE-2011-1017 (buffer overflow in ldm_frag_add) is not sufficient. The original patch in commit c340b1d64000 ("fs/partitions/ldm.c: fix oops caused by corrupted partition table") does not consider that, for subsequent fragments, previously allocated memory is used. [1] http://lkml.org/lkml/2011/5/6/407 Reported-by: Ben Hutchings Signed-off-by: Timo Warns Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/partitions/ldm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c index 9fea43ba9fa6..db07e6dcc0e9 100644 --- a/fs/partitions/ldm.c +++ b/fs/partitions/ldm.c @@ -1335,6 +1335,11 @@ static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags) list_add_tail (&f->list, frags); found: + if (rec >= f->num) { + ldm_error("REC value (%d) exceeds NUM value (%d)", rec, f->num); + return false; + } + if (f->map & (1 << rec)) { ldm_error ("Duplicate VBLK, part %d.", rec); f->map &= 0x7F; /* Mark the group as broken */ -- cgit v1.2.3 From 081104261c084dee58518bcbbd23e95910e3fbe3 Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Thu, 12 May 2011 04:13:54 -0500 Subject: seqlock: Don't smp_rmb in seqlock reader spin loop commit 5db1256a5131d3b133946fa02ac9770a784e6eb2 upstream. Move the smp_rmb after cpu_relax loop in read_seqlock and add ACCESS_ONCE to make sure the test and return are consistent. A multi-threaded core in the lab didn't like the update from 2.6.35 to 2.6.36, to the point it would hang during boot when multiple threads were active. Bisection showed af5ab277ded04bd9bc6b048c5a2f0e7d70ef0867 (clockevents: Remove the per cpu tick skew) as the culprit and it is supported with stack traces showing xtime_lock waits including tick_do_update_jiffies64 and/or update_vsyscall. Experimentation showed the combination of cpu_relax and smp_rmb was significantly slowing the progress of other threads sharing the core, and this patch is effective in avoiding the hang. A theory is the rmb is affecting the whole core while the cpu_relax is causing a resource rebalance flush, together they cause an interfernce cadance that is unbroken when the seqlock reader has interrupts disabled. At first I was confused why the refactor in 3c22cd5709e8143444a6d08682a87f4c57902df3 (kernel: optimise seqlock) didn't affect this patch application, but after some study that affected seqcount not seqlock. The new seqcount was not factored back into the seqlock. I defer that the future. While the removal of the timer interrupt offset created contention for the xtime lock while a cpu does the additonal work to update the system clock, the seqlock implementation with the tight rmb spin loop goes back much further, and is just waiting for the right trigger. Signed-off-by: Milton Miller Cc: Cc: Linus Torvalds Cc: Andi Kleen Cc: Nick Piggin Cc: Benjamin Herrenschmidt Cc: Anton Blanchard Cc: Paul McKenney Acked-by: Eric Dumazet Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/%3Cseqlock-rmb%40mdm.bga.com%3E Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- include/linux/seqlock.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h index 632205ccc25d..4c3257d5ade7 100644 --- a/include/linux/seqlock.h +++ b/include/linux/seqlock.h @@ -88,12 +88,12 @@ static __always_inline unsigned read_seqbegin(const seqlock_t *sl) unsigned ret; repeat: - ret = sl->sequence; - smp_rmb(); + ret = ACCESS_ONCE(sl->sequence); if (unlikely(ret & 1)) { cpu_relax(); goto repeat; } + smp_rmb(); return ret; } -- cgit v1.2.3 From 9657a2cc096762b77ba5743b15bf0c2a6cb829c1 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Mon, 16 May 2011 12:09:29 +0200 Subject: ALSA: HDA: Use one dmic only for Dell Studio 1558 commit e033ebfb399227e01686260ac271029011bc6b47 upstream. There are no signs of a dmic at node 0x0b, so the user is left with an additional internal mic which does not exist. This commit removes that non-existing mic. BugLink: http://bugs.launchpad.net/bugs/731706 Reported-by: James Page Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_sigmatel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 3532d2c37838..22da87ff4ff7 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1623,7 +1623,7 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02fe, "Dell Studio XPS 1645", STAC_DELL_M6_BOTH), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0413, - "Dell Studio 1558", STAC_DELL_M6_BOTH), + "Dell Studio 1558", STAC_DELL_M6_DMIC), {} /* terminator */ }; -- cgit v1.2.3 From 349419f96bd74bf077d6eb4ee5e4b9dd0902ab47 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 14 May 2011 17:21:28 -0700 Subject: ASoC: Ensure output PGA is enabled for line outputs in wm_hubs commit d0b48af6c2b887354d0893e598d92911ce52620e upstream. Also fix a left/right typo while we're at it. Signed-off-by: Mark Brown Acked-by: Liam Girdwood Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/soc/codecs/wm_hubs.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 5093a767a72d..f43236d1c55a 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -752,17 +752,17 @@ static const struct snd_soc_dapm_route analogue_routes[] = { static const struct snd_soc_dapm_route lineout1_diff_routes[] = { { "LINEOUT1 Mixer", "IN1L Switch", "IN1L PGA" }, { "LINEOUT1 Mixer", "IN1R Switch", "IN1R PGA" }, - { "LINEOUT1 Mixer", "Output Switch", "Left Output Mixer" }, + { "LINEOUT1 Mixer", "Output Switch", "Left Output PGA" }, { "LINEOUT1N Driver", NULL, "LINEOUT1 Mixer" }, { "LINEOUT1P Driver", NULL, "LINEOUT1 Mixer" }, }; static const struct snd_soc_dapm_route lineout1_se_routes[] = { - { "LINEOUT1N Mixer", "Left Output Switch", "Left Output Mixer" }, - { "LINEOUT1N Mixer", "Right Output Switch", "Left Output Mixer" }, + { "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" }, + { "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" }, - { "LINEOUT1P Mixer", "Left Output Switch", "Left Output Mixer" }, + { "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" }, { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" }, { "LINEOUT1P Driver", NULL, "LINEOUT1P Mixer" }, @@ -771,17 +771,17 @@ static const struct snd_soc_dapm_route lineout1_se_routes[] = { static const struct snd_soc_dapm_route lineout2_diff_routes[] = { { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" }, { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" }, - { "LINEOUT2 Mixer", "Output Switch", "Right Output Mixer" }, + { "LINEOUT2 Mixer", "Output Switch", "Right Output PGA" }, { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" }, { "LINEOUT2P Driver", NULL, "LINEOUT2 Mixer" }, }; static const struct snd_soc_dapm_route lineout2_se_routes[] = { - { "LINEOUT2N Mixer", "Left Output Switch", "Left Output Mixer" }, - { "LINEOUT2N Mixer", "Right Output Switch", "Left Output Mixer" }, + { "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" }, + { "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" }, - { "LINEOUT2P Mixer", "Right Output Switch", "Right Output Mixer" }, + { "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" }, { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" }, { "LINEOUT2P Driver", NULL, "LINEOUT2P Mixer" }, -- cgit v1.2.3 From c7f49dc31ed8d10c288e034a82e1214f2c0c63c2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 May 2011 12:18:38 -0700 Subject: ASoC: Add some missing volume update bit sets for wm_hubs devices commit fb5af53d421d80725172427e9076f6e889603df6 upstream. Signed-off-by: Mark Brown Acked-by: Liam Girdwood Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/soc/codecs/wm_hubs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index f43236d1c55a..622429503769 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -799,17 +799,21 @@ int wm_hubs_add_analogue_controls(struct snd_soc_codec *codec) snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, WM8993_IN2_VU, WM8993_IN2_VU); + snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_LEFT, + WM8993_SPKOUT_VU, WM8993_SPKOUT_VU); snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_RIGHT, WM8993_SPKOUT_VU, WM8993_SPKOUT_VU); snd_soc_update_bits(codec, WM8993_LEFT_OUTPUT_VOLUME, - WM8993_HPOUT1L_ZC, WM8993_HPOUT1L_ZC); + WM8993_HPOUT1_VU | WM8993_HPOUT1L_ZC, + WM8993_HPOUT1_VU | WM8993_HPOUT1L_ZC); snd_soc_update_bits(codec, WM8993_RIGHT_OUTPUT_VOLUME, WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC, WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC); snd_soc_update_bits(codec, WM8993_LEFT_OPGA_VOLUME, - WM8993_MIXOUTL_ZC, WM8993_MIXOUTL_ZC); + WM8993_MIXOUTL_ZC | WM8993_MIXOUT_VU, + WM8993_MIXOUTL_ZC | WM8993_MIXOUT_VU); snd_soc_update_bits(codec, WM8993_RIGHT_OPGA_VOLUME, WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU, WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU); -- cgit v1.2.3 From bb590ef04557a915fe6bd2818c23ed9cd46c5f2f Mon Sep 17 00:00:00 2001 From: Andrew Barry Date: Tue, 24 May 2011 17:12:52 -0700 Subject: mm/page_alloc.c: prevent unending loop in __alloc_pages_slowpath() commit cfa54a0fcfc1017c6f122b6f21aaba36daa07f71 upstream. I believe I found a problem in __alloc_pages_slowpath, which allows a process to get stuck endlessly looping, even when lots of memory is available. Running an I/O and memory intensive stress-test I see a 0-order page allocation with __GFP_IO and __GFP_WAIT, running on a system with very little free memory. Right about the same time that the stress-test gets killed by the OOM-killer, the utility trying to allocate memory gets stuck in __alloc_pages_slowpath even though most of the systems memory was freed by the oom-kill of the stress-test. The utility ends up looping from the rebalance label down through the wait_iff_congested continiously. Because order=0, __alloc_pages_direct_compact skips the call to get_page_from_freelist. Because all of the reclaimable memory on the system has already been reclaimed, __alloc_pages_direct_reclaim skips the call to get_page_from_freelist. Since there is no __GFP_FS flag, the block with __alloc_pages_may_oom is skipped. The loop hits the wait_iff_congested, then jumps back to rebalance without ever trying to get_page_from_freelist. This loop repeats infinitely. The test case is pretty pathological. Running a mix of I/O stress-tests that do a lot of fork() and consume all of the system memory, I can pretty reliably hit this on 600 nodes, in about 12 hours. 32GB/node. Signed-off-by: Andrew Barry Signed-off-by: Minchan Kim Reviewed-by: Rik van Riel Acked-by: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- mm/page_alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 68404aa8523d..98c699d9136f 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2027,6 +2027,7 @@ restart: */ alloc_flags = gfp_to_alloc_flags(gfp_mask); +rebalance: /* This is the last chance, in general, before the goto nopage. */ page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist, high_zoneidx, alloc_flags & ~ALLOC_NO_WATERMARKS, @@ -2034,7 +2035,6 @@ restart: if (page) goto got_pg; -rebalance: /* Allocate without watermarks if the context allows */ if (alloc_flags & ALLOC_NO_WATERMARKS) { page = __alloc_pages_high_priority(gfp_mask, order, -- cgit v1.2.3 From fb3085bac19be01477364db550c4b9d4c0e13077 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 24 May 2011 16:48:54 +0200 Subject: loop: limit 'max_part' module param to DISK_MAX_PARTS commit 78f4bb367fd147a0e7e3998ba6e47109999d8814 upstream. The 'max_part' parameter controls the number of maximum partition a loop block device can have. However if a user specifies very large value it would exceed the limitation of device minor number and can cause a kernel panic (or, at least, produce invalid device nodes in some cases). On my desktop system, following command kills the kernel. On qemu, it triggers similar oops but the kernel was alive: $ sudo modprobe loop max_part0000 ------------[ cut here ]------------ kernel BUG at /media/Linux_Data/project/linux/fs/sysfs/group.c:65! invalid opcode: 0000 [#1] SMP last sysfs file: CPU 0 Modules linked in: loop(+) Pid: 43, comm: insmod Tainted: G W 2.6.39-qemu+ #155 Bochs Bochs RIP: 0010:[] [] internal_create_group= +0x2a/0x170 RSP: 0018:ffff880007b3fde8 EFLAGS: 00000246 RAX: 00000000ffffffef RBX: ffff880007b3d878 RCX: 00000000000007b4 RDX: ffffffff8152da50 RSI: 0000000000000000 RDI: ffff880007b3d878 RBP: ffff880007b3fe38 R08: ffff880007b3fde8 R09: 0000000000000000 R10: ffff88000783b4a8 R11: ffff880007b3d878 R12: ffffffff8152da50 R13: ffff880007b3d868 R14: 0000000000000000 R15: ffff880007b3d800 FS: 0000000002137880(0063) GS:ffff880007c00000(0000) knlGS:00000000000000= 00 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000422680 CR3: 0000000007b50000 CR4: 00000000000006b0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 0000000000000000 DR7: 0000000000000000 Process insmod (pid: 43, threadinfo ffff880007b3e000, task ffff880007afb9c= 0) Stack: ffff880007b3fe58 ffffffff811e66dd ffff880007b3fe58 ffffffff811e570b 0000000000000010 ffff880007b3d800 ffff880007a7b390 ffff880007b3d868 0000000000400920 ffff880007b3d800 ffff880007b3fe48 ffffffff8113cfc8 Call Trace: [] ? device_add+0x4bc/0x5af [] ? dev_set_name+0x3c/0x3e [] sysfs_create_group+0xe/0x12 [] blk_trace_init_sysfs+0x14/0x16 [] blk_register_queue+0x47/0xf7 [] add_disk+0xdf/0x290 [] loop_init+0xeb/0x1b8 [loop] [] ? 0xffffffffa0005fff [] do_one_initcall+0x7a/0x12e [] sys_init_module+0x9c/0x1e0 [] system_call_fastpath+0x16/0x1b Code: c3 55 48 89 e5 41 57 41 56 41 89 f6 41 55 41 54 49 89 d4 53 48 89 fb= 48 83 ec 28 48 85 ff 74 0b 85 f6 75 0b 48 83 7f 30 00 75 14 <0f> 0b eb fe = 48 83 7f 30 00 b9 ea ff ff ff 0f 84 18 01 00 00 49 RIP [] internal_create_group+0x2a/0x170 RSP ---[ end trace a123eb592043acad ]--- Signed-off-by: Namhyung Kim Cc: Laurent Vivier Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/block/loop.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 6120922f459f..7ea9163b47a2 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1612,6 +1612,9 @@ static int __init loop_init(void) if (max_part > 0) part_shift = fls(max_part); + if ((1UL << part_shift) > DISK_MAX_PARTS) + return -EINVAL; + if (max_loop > 1UL << (MINORBITS - part_shift)) return -EINVAL; -- cgit v1.2.3 From dfba2b9005ebcc9eea048dc4e7d29156747b1987 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 24 May 2011 16:48:55 +0200 Subject: loop: handle on-demand devices correctly commit a1c15c59feee36267c43142a41152fbf7402afb6 upstream. When finding or allocating a loop device, loop_probe() did not take partition numbers into account so that it can result to a different device. Consider following example: $ sudo modprobe loop max_part=15 $ ls -l /dev/loop* brw-rw---- 1 root disk 7, 0 2011-05-24 22:16 /dev/loop0 brw-rw---- 1 root disk 7, 16 2011-05-24 22:16 /dev/loop1 brw-rw---- 1 root disk 7, 32 2011-05-24 22:16 /dev/loop2 brw-rw---- 1 root disk 7, 48 2011-05-24 22:16 /dev/loop3 brw-rw---- 1 root disk 7, 64 2011-05-24 22:16 /dev/loop4 brw-rw---- 1 root disk 7, 80 2011-05-24 22:16 /dev/loop5 brw-rw---- 1 root disk 7, 96 2011-05-24 22:16 /dev/loop6 brw-rw---- 1 root disk 7, 112 2011-05-24 22:16 /dev/loop7 $ sudo mknod /dev/loop8 b 7 128 $ sudo losetup /dev/loop8 ~/temp/disk-with-3-parts.img $ sudo losetup -a /dev/loop128: [0805]:278201 (/home/namhyung/temp/disk-with-3-parts.img) $ ls -l /dev/loop* brw-rw---- 1 root disk 7, 0 2011-05-24 22:16 /dev/loop0 brw-rw---- 1 root disk 7, 16 2011-05-24 22:16 /dev/loop1 brw-rw---- 1 root disk 7, 2048 2011-05-24 22:18 /dev/loop128 brw-rw---- 1 root disk 7, 2049 2011-05-24 22:18 /dev/loop128p1 brw-rw---- 1 root disk 7, 2050 2011-05-24 22:18 /dev/loop128p2 brw-rw---- 1 root disk 7, 2051 2011-05-24 22:18 /dev/loop128p3 brw-rw---- 1 root disk 7, 32 2011-05-24 22:16 /dev/loop2 brw-rw---- 1 root disk 7, 48 2011-05-24 22:16 /dev/loop3 brw-rw---- 1 root disk 7, 64 2011-05-24 22:16 /dev/loop4 brw-rw---- 1 root disk 7, 80 2011-05-24 22:16 /dev/loop5 brw-rw---- 1 root disk 7, 96 2011-05-24 22:16 /dev/loop6 brw-rw---- 1 root disk 7, 112 2011-05-24 22:16 /dev/loop7 brw-r--r-- 1 root root 7, 128 2011-05-24 22:17 /dev/loop8 After this patch, /dev/loop8 - instead of /dev/loop128 - was accessed correctly. In addition, 'range' passed to blk_register_region() should include all range of dev_t that LOOP_MAJOR can address. It does not need to be limited by partition numbers unless 'max_loop' param was specified. Signed-off-by: Namhyung Kim Cc: Laurent Vivier Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/block/loop.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 7ea9163b47a2..df27578d12a0 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1579,7 +1579,7 @@ static struct kobject *loop_probe(dev_t dev, int *part, void *data) struct kobject *kobj; mutex_lock(&loop_devices_mutex); - lo = loop_init_one(dev & MINORMASK); + lo = loop_init_one(MINOR(dev) >> part_shift); kobj = lo ? get_disk(lo->lo_disk) : ERR_PTR(-ENOMEM); mutex_unlock(&loop_devices_mutex); @@ -1620,10 +1620,10 @@ static int __init loop_init(void) if (max_loop) { nr = max_loop; - range = max_loop; + range = max_loop << part_shift; } else { nr = 8; - range = 1UL << (MINORBITS - part_shift); + range = 1UL << MINORBITS; } if (register_blkdev(LOOP_MAJOR, "loop")) @@ -1662,7 +1662,7 @@ static void __exit loop_exit(void) unsigned long range; struct loop_device *lo, *next; - range = max_loop ? max_loop : 1UL << (MINORBITS - part_shift); + range = max_loop ? max_loop << part_shift : 1UL << MINORBITS; list_for_each_entry_safe(lo, next, &loop_devices, lo_list) loop_del_one(lo); -- cgit v1.2.3 From 5bb5bf5a45b7c442459ab71f069c28215ae5a201 Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Sun, 20 Mar 2011 13:51:13 +0000 Subject: USB: CP210x Add 4 Device IDs for AC-Services Devices commit 4eff0b40a7174896b860312910e0db51f2dcc567 upstream. This patch adds 4 device IDs for CP2102 based devices manufactured by AC-Services. See http://www.ac-services.eu for further info. Signed-off-by: Craig Shelley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/cp210x.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 1a85938ff0e5..2082cba4f464 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -112,6 +112,10 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */ { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ { USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */ + { USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */ + { USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */ + { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */ + { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */ -- cgit v1.2.3 From 48e9e30804a4a52ef85f5f31abeafe12178c67a6 Mon Sep 17 00:00:00 2001 From: Elizabeth Jennifer Myers Date: Sat, 16 Apr 2011 14:49:51 -0400 Subject: USB: moto_modem: Add USB identifier for the Motorola VE240. commit 3938a0b32dc12229e76735679b37095bc2bc1578 upstream. Tested on my phone, the ttyUSB device is created and is fully functional. Signed-off-by: Elizabeth Jennifer Myers Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/moto_modem.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c index cf1718394e18..0147042ebcc6 100644 --- a/drivers/usb/serial/moto_modem.c +++ b/drivers/usb/serial/moto_modem.c @@ -25,6 +25,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x05c6, 0x3197) }, /* unknown Motorola phone */ { USB_DEVICE(0x0c44, 0x0022) }, /* unknown Mororola phone */ { USB_DEVICE(0x22b8, 0x2a64) }, /* Motorola KRZR K1m */ + { USB_DEVICE(0x22b8, 0x2c84) }, /* Motorola VE240 phone */ { USB_DEVICE(0x22b8, 0x2c64) }, /* Motorola V950 phone */ { }, }; -- cgit v1.2.3 From e2835a5f7f667338aca34a7fada6f7c24423574b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benedek=20L=C3=A1szl=C3=B3?= Date: Wed, 20 Apr 2011 03:22:21 +0200 Subject: USB: serial: ftdi_sio: adding support for TavIR STK500 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 37909fe588c9e09ab57cd267e98678a17ceda64a upstream. Adding support for the TavIR STK500 (id 0403:FA33) Atmel AVR programmer device based on FTDI FT232RL. Signed-off-by: Benedek László Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 8ed7c888c7d4..3d68c97f9037 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -565,6 +565,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_IBS_APP70_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) }, /* * ELV devices: */ diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 0060913edb91..5eae8251dadc 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -491,6 +491,11 @@ /* www.canusb.com Lawicel CANUSB device (FTDI_VID) */ #define FTDI_CANUSB_PID 0xFFA8 /* Product Id */ +/* + * TavIR AVR product ids (FTDI_VID) + */ +#define FTDI_TAVIR_STK500_PID 0xFA33 /* STK500 AVR programmer */ + /********************************/ -- cgit v1.2.3 From 4f94d4382c06a24196673a2e408dd257ac0ffbb4 Mon Sep 17 00:00:00 2001 From: Hermann Kneissel Date: Fri, 29 Apr 2011 08:58:43 +0200 Subject: USB: gamin_gps: Fix for data transfer problems in native mode commit b4026c4584cd70858d4d3450abfb1cd0714d4f32 upstream. This patch fixes a problem where data received from the gps is sometimes transferred incompletely to the serial port. If used in native mode now all data received via the bulk queue will be forwarded to the serial port. Signed-off-by: Hermann Kneissel Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/garmin_gps.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index a42b29a695b2..0f0a122c6525 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -1,7 +1,7 @@ /* * Garmin GPS driver * - * Copyright (C) 2006-2009 Hermann Kneissel herkne@users.sourceforge.net + * Copyright (C) 2006-2011 Hermann Kneissel herkne@gmx.de * * The latest version of the driver can be found at * http://sourceforge.net/projects/garmin-gps/ @@ -51,7 +51,7 @@ static int debug; */ #define VERSION_MAJOR 0 -#define VERSION_MINOR 33 +#define VERSION_MINOR 36 #define _STR(s) #s #define _DRIVER_VERSION(a, b) "v" _STR(a) "." _STR(b) @@ -410,6 +410,7 @@ static int gsp_send_ack(struct garmin_data *garmin_data_p, __u8 pkt_id) */ static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count) { + unsigned long flags; const __u8 *recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET; __le32 *usbdata = (__le32 *) garmin_data_p->inbuffer; @@ -458,7 +459,9 @@ static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count) /* if this was an abort-transfer command, flush all queued data. */ if (isAbortTrfCmnd(garmin_data_p->inbuffer)) { + spin_lock_irqsave(&garmin_data_p->lock, flags); garmin_data_p->flags |= FLAGS_DROP_DATA; + spin_unlock_irqrestore(&garmin_data_p->lock, flags); pkt_clear(garmin_data_p); } @@ -943,7 +946,7 @@ static int garmin_open(struct tty_struct *tty, struct usb_serial_port *port) spin_lock_irqsave(&garmin_data_p->lock, flags); garmin_data_p->mode = initial_mode; garmin_data_p->count = 0; - garmin_data_p->flags = 0; + garmin_data_p->flags &= FLAGS_SESSION_REPLY1_SEEN; spin_unlock_irqrestore(&garmin_data_p->lock, flags); /* shutdown any bulk reads that might be going on */ @@ -1178,7 +1181,8 @@ static int garmin_write_room(struct tty_struct *tty) static void garmin_read_process(struct garmin_data *garmin_data_p, - unsigned char *data, unsigned data_length) + unsigned char *data, unsigned data_length, + int bulk_data) { unsigned long flags; @@ -1193,7 +1197,8 @@ static void garmin_read_process(struct garmin_data *garmin_data_p, send it directly to the tty port */ if (garmin_data_p->flags & FLAGS_QUEUING) { pkt_add(garmin_data_p, data, data_length); - } else if (getLayerId(data) == GARMIN_LAYERID_APPL) { + } else if (bulk_data || + getLayerId(data) == GARMIN_LAYERID_APPL) { spin_lock_irqsave(&garmin_data_p->lock, flags); garmin_data_p->flags |= APP_RESP_SEEN; @@ -1237,7 +1242,7 @@ static void garmin_read_bulk_callback(struct urb *urb) usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); - garmin_read_process(garmin_data_p, data, urb->actual_length); + garmin_read_process(garmin_data_p, data, urb->actual_length, 1); if (urb->actual_length == 0 && 0 != (garmin_data_p->flags & FLAGS_BULK_IN_RESTART)) { @@ -1347,7 +1352,7 @@ static void garmin_read_int_callback(struct urb *urb) __func__, garmin_data_p->serial_num); } - garmin_read_process(garmin_data_p, data, urb->actual_length); + garmin_read_process(garmin_data_p, data, urb->actual_length, 0); port->interrupt_in_urb->dev = port->serial->dev; retval = usb_submit_urb(urb, GFP_ATOMIC); @@ -1462,6 +1467,7 @@ static int garmin_attach(struct usb_serial *serial) garmin_data_p->timer.function = timeout_handler; garmin_data_p->port = port; garmin_data_p->state = 0; + garmin_data_p->flags = 0; garmin_data_p->count = 0; usb_set_serial_port_data(port, garmin_data_p); -- cgit v1.2.3 From 207e1f6a999784bc8e7047f4ae9f72c73d48a9b2 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Fri, 13 May 2011 17:03:02 +0200 Subject: usb/gadget: at91sam9g20 fix end point max packet size commit bf1f0a05d472e33dda8e5e69525be1584cdbd03a upstream. on 9g20 they are the same as the 9260 Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Nicolas Ferre Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/gadget/at91_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index eaa79c8a9b8c..ce3e47930f72 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1701,7 +1701,7 @@ static int __init at91udc_probe(struct platform_device *pdev) } /* newer chips have more FIFO memory than rm9200 */ - if (cpu_is_at91sam9260()) { + if (cpu_is_at91sam9260() || cpu_is_at91sam9g20()) { udc->ep[0].maxpacket = 64; udc->ep[3].maxpacket = 64; udc->ep[4].maxpacket = 512; -- cgit v1.2.3 From d4ffbbb11ad59a922ea546eda88316a3511890fe Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 13 May 2011 16:53:48 +0300 Subject: usb: gadget: rndis: don't test against req->length commit 472b91274a6c6857877b5caddb875dcb5ecdfcb8 upstream. composite.c always sets req->length to zero and expects function driver's setup handlers to return the amount of bytes to be used on req->length. If we test against req->length w_length will always be greater than req->length thus making us always stall that particular SEND_ENCAPSULATED_COMMAND request. Tested against a Windows XP SP3. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/gadget/f_rndis.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 882484a40398..fa12ec8364ef 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -420,8 +420,7 @@ rndis_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) */ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) | USB_CDC_SEND_ENCAPSULATED_COMMAND: - if (w_length > req->length || w_value - || w_index != rndis->ctrl_id) + if (w_value || w_index != rndis->ctrl_id) goto invalid; /* read the request; process it later */ value = w_length; -- cgit v1.2.3 From 9a355f7cab321c8f700d367b5b663a7364c6e19f Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 13 May 2011 13:10:01 -0700 Subject: xhci: Fix full speed bInterval encoding. commit b513d44751bfb609a3c20463f764c8ce822d63e9 upstream. Dmitry's patch dfa49c4ad120a784ef1ff0717168aa79f55a483a USB: xhci - fix math in xhci_get_endpoint_interval() introduced a bug. The USB 2.0 spec says that full speed isochronous endpoints' bInterval must be decoded as an exponent to a power of two (e.g. interval = 2^(bInterval - 1)). Full speed interrupt endpoints, on the other hand, don't use exponents, and the interval in frames is encoded straight into bInterval. Dmitry's patch was supposed to fix up the full speed isochronous to parse bInterval as an exponent, but instead it changed the *interrupt* endpoint bInterval decoding. The isochronous endpoint encoding was the same. This caused full speed devices with interrupt endpoints (including mice, hubs, and USB to ethernet devices) to fail under NEC 0.96 xHCI host controllers: [ 100.909818] xhci_hcd 0000:06:00.0: add ep 0x83, slot id 1, new drop flags = 0x0, new add flags = 0x99, new slot info = 0x38100000 [ 100.909821] xhci_hcd 0000:06:00.0: xhci_check_bandwidth called for udev ffff88011f0ea000 ... [ 100.910187] xhci_hcd 0000:06:00.0: ERROR: unexpected command completion code 0x11. [ 100.910190] xhci_hcd 0000:06:00.0: xhci_reset_bandwidth called for udev ffff88011f0ea000 When the interrupt endpoint was added and a Configure Endpoint command was issued to the host, the host controller would return a very odd error message (0x11 means "Slot Not Enabled", which isn't true because the slot was enabled). Probably the host controller was getting very confused with the bad encoding. Signed-off-by: Sarah Sharp Cc: Dmitry Torokhov Reported-by: Thomas Lindroth Tested-by: Thomas Lindroth Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/xhci-mem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 7ddb69f3038f..fb0a073470d7 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1034,12 +1034,12 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev, * nearest power of 2. */ case USB_SPEED_FULL: - if (usb_endpoint_xfer_int(&ep->desc)) { + if (usb_endpoint_xfer_isoc(&ep->desc)) { interval = xhci_parse_exponent_interval(udev, ep); break; } /* - * Fall through for isochronous endpoint interval decoding + * Fall through for interrupt endpoint interval decoding * since it uses the same rules as low speed interrupt * endpoints. */ -- cgit v1.2.3 From 545e0ed639e969e5c02921fab5733f7c95693cb3 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 10 Sep 2010 16:37:05 -0400 Subject: OHCI: work around for nVidia shutdown problem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ upstream commit 5f528de0ef9b3e092e276d95930830b847b33dc4 ] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 3df7169e73fc1d71a39cffeacc969f6840cdf52b upstream. This patch (as1417) fixes a problem affecting some (or all) nVidia chipsets. When the computer is shut down, the OHCI controllers continue to power the USB buses and evidently they drive a Reset signal out all their ports. This prevents attached devices from going to low power. Mouse LEDs stay on, for example, which is disconcerting for users and a drain on laptop batteries. The fix involves leaving each OHCI controller in the OPERATIONAL state during system shutdown rather than putting it in the RESET state. Although this nominally means the controller is running, in fact it's not doing very much since all the schedules are all disabled. However there is ongoing DMA to the Host Controller Communications Area, so the patch also disables the bus-master capability of all PCI USB controllers after the shutdown routine runs. The fix is applied only to nVidia-based PCI OHCI controllers, so it shouldn't cause problems on systems using other hardware. As an added safety measure, in case the kernel encounters one of these running controllers during boot, the patch changes quirk_usb_handoff_ohci() (which runs early on during PCI discovery) to reset the controller before anything bad can happen. Reported-by: Pali Rohár Signed-off-by: Alan Stern Signed-off-by: Andi Kleen CC: David Brownell Tested-by: Pali Rohár Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd-pci.c | 4 +++- drivers/usb/host/ohci-hcd.c | 9 ++++++++- drivers/usb/host/ohci-pci.c | 18 ++++++++++++++++++ drivers/usb/host/ohci.h | 1 + drivers/usb/host/pci-quirks.c | 18 +++++++++++------- 5 files changed, 41 insertions(+), 9 deletions(-) diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 1cf2d1e79a5c..3667660aee98 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -317,8 +317,10 @@ void usb_hcd_pci_shutdown(struct pci_dev *dev) if (!hcd) return; - if (hcd->driver->shutdown) + if (hcd->driver->shutdown) { hcd->driver->shutdown(hcd); + pci_disable_device(dev); + } } EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index fc576557d8a5..cc5a8e6db8cb 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -398,7 +398,14 @@ ohci_shutdown (struct usb_hcd *hcd) ohci = hcd_to_ohci (hcd); ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); - ohci_usb_reset (ohci); + ohci->hc_control = ohci_readl(ohci, &ohci->regs->control); + + /* If the SHUTDOWN quirk is set, don't put the controller in RESET */ + ohci->hc_control &= (ohci->flags & OHCI_QUIRK_SHUTDOWN ? + OHCI_CTRL_RWC | OHCI_CTRL_HCFS : + OHCI_CTRL_RWC); + ohci_writel(ohci, ohci->hc_control, &ohci->regs->control); + /* flush the writes */ (void) ohci_readl (ohci, &ohci->regs->control); } diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index b8a1148f248e..948a35335150 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -201,6 +201,20 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd) return 0; } +/* nVidia controllers continue to drive Reset signalling on the bus + * even after system shutdown, wasting power. This flag tells the + * shutdown routine to leave the controller OPERATIONAL instead of RESET. + */ +static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + + ohci->flags |= OHCI_QUIRK_SHUTDOWN; + ohci_dbg(ohci, "enabled nVidia shutdown quirk\n"); + + return 0; +} + /* * The hardware normally enables the A-link power management feature, which * lets the system lower the power consumption in idle states. @@ -332,6 +346,10 @@ static const struct pci_device_id ohci_pci_quirks[] = { PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399), .driver_data = (unsigned long)ohci_quirk_amd700, }, + { + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID), + .driver_data = (unsigned long) ohci_quirk_nvidia_shutdown, + }, /* FIXME for some of the early AMD 760 southbridges, OHCI * won't work at all. blacklist them. diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 5bf15fed0d9f..51facb985c84 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -403,6 +403,7 @@ struct ohci_hcd { #define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */ #define OHCI_QUIRK_AMD_ISO 0x200 /* ISO transfers*/ #define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */ +#define OHCI_QUIRK_SHUTDOWN 0x800 /* nVidia power bug */ // there are also chip quirks/bugs in init logic struct work_struct nec_work; /* Worker for NEC quirk */ diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 83b5f9cea85a..464ed977b45d 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -169,6 +169,7 @@ static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx) static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) { void __iomem *base; + u32 control; if (!mmio_resource_enabled(pdev, 0)) return; @@ -177,10 +178,14 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) if (base == NULL) return; + control = readl(base + OHCI_CONTROL); + /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ -#ifndef __hppa__ -{ - u32 control = readl(base + OHCI_CONTROL); +#ifdef __hppa__ +#define OHCI_CTRL_MASK (OHCI_CTRL_RWC | OHCI_CTRL_IR) +#else +#define OHCI_CTRL_MASK OHCI_CTRL_RWC + if (control & OHCI_CTRL_IR) { int wait_time = 500; /* arbitrary; 5 seconds */ writel(OHCI_INTR_OC, base + OHCI_INTRENABLE); @@ -194,13 +199,12 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) dev_warn(&pdev->dev, "OHCI: BIOS handoff failed" " (BIOS bug?) %08x\n", readl(base + OHCI_CONTROL)); - - /* reset controller, preserving RWC */ - writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL); } -} #endif + /* reset controller, preserving RWC (and possibly IR) */ + writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL); + /* * disable interrupts */ -- cgit v1.2.3 From 4e79c3eb206ca9d851e3eacbbbfc5b38aff5583a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 16 May 2011 12:15:19 -0400 Subject: OHCI: fix regression caused by nVidia shutdown workaround commit 2b7aaf503d56216b847c8265421d2a7d9b42df3e upstream. This patch (as1463) fixes a regression caused by commit 3df7169e73fc1d71a39cffeacc969f6840cdf52b (OHCI: work around for nVidia shutdown problem). The original problem encountered by people using NVIDIA chipsets was that USB devices were not turning off when the system shut down. For example, the LED on an optical mouse would remain on, draining a laptop's battery. The problem was caused by a bug in the chipset; an OHCI controller in the Reset state would continue to drive a bus reset signal even after system shutdown. The workaround was to put the controllers into the Suspend state instead. It turns out that later NVIDIA chipsets do not suffer from this bug. Instead some have the opposite bug: If a system is shut down while an OHCI controller is in the Suspend state, USB devices remain powered! On other systems, shutting down with a Suspended controller causes the system to reboot immediately. Thus, working around the original bug on some machines exposes other bugs on other machines. The best solution seems to be to limit the workaround to OHCI controllers with a low-numbered PCI product ID. I don't know exactly at what point NVIDIA changed their chipsets; the value used here is a guess. So far it was worked out okay for all the people who have tested it. This fixes Bugzilla #35032. Signed-off-by: Alan Stern Tested-by: Andre "Osku" Schmidt Tested-by: Yury Siamashka Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/ohci-pci.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 948a35335150..67f83e564118 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -207,10 +207,18 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd) */ static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd) { + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); struct ohci_hcd *ohci = hcd_to_ohci(hcd); - ohci->flags |= OHCI_QUIRK_SHUTDOWN; - ohci_dbg(ohci, "enabled nVidia shutdown quirk\n"); + /* Evidently nVidia fixed their later hardware; this is a guess at + * the changeover point. + */ +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB 0x026d + + if (pdev->device < PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB) { + ohci->flags |= OHCI_QUIRK_SHUTDOWN; + ohci_dbg(ohci, "enabled nVidia shutdown quirk\n"); + } return 0; } -- cgit v1.2.3 From 117c0bc1b8a17622e4f93a744ba492b5da9d9fee Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 13 May 2011 21:47:23 +0200 Subject: p54usb: add zoom 4410 usbid commit 9368a9a2378ab721f82f59430a135b4ce4ff5109 upstream. Reported-by: Mark Davis Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/p54/p54usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index e3924a99f44b..40e248bb8ae1 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -82,6 +82,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ + {USB_DEVICE(0x083a, 0xc501)}, /* Zoom Wireless-G 4410 */ {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */ {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */ -- cgit v1.2.3 From e06b5bf516bfcc0f55d0577b14261fee1824c646 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Tue, 17 May 2011 00:50:33 -0500 Subject: eCryptfs: Allow 2 scatterlist entries for encrypted filenames commit 8d08dab786ad5cc2aca2bf870de370144b78c85a upstream. The buffers allocated while encrypting and decrypting long filenames can sometimes straddle two pages. In this situation, virt_to_scatterlist() will return -ENOMEM, causing the operation to fail and the user will get scary error messages in their logs: kernel: ecryptfs_write_tag_70_packet: Internal error whilst attempting to convert filename memory to scatterlist; expected rc = 1; got rc = [-12]. block_aligned_filename_size = [272] kernel: ecryptfs_encrypt_filename: Error attempting to generate tag 70 packet; rc = [-12] kernel: ecryptfs_encrypt_and_encode_filename: Error attempting to encrypt filename; rc = [-12] kernel: ecryptfs_lookup: Error attempting to encrypt and encode filename; rc = [-12] The solution is to allow up to 2 scatterlist entries to be used. Signed-off-by: Tyler Hicks Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ecryptfs/keystore.c | 46 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index d6e935541a0b..07f23c508192 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -482,8 +482,8 @@ struct ecryptfs_write_tag_70_packet_silly_stack { struct mutex *tfm_mutex; char *block_aligned_filename; struct ecryptfs_auth_tok *auth_tok; - struct scatterlist src_sg; - struct scatterlist dst_sg; + struct scatterlist src_sg[2]; + struct scatterlist dst_sg[2]; struct blkcipher_desc desc; char iv[ECRYPTFS_MAX_IV_BYTES]; char hash[ECRYPTFS_TAG_70_DIGEST_SIZE]; @@ -696,23 +696,21 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, memcpy(&s->block_aligned_filename[s->num_rand_bytes], filename, filename_size); rc = virt_to_scatterlist(s->block_aligned_filename, - s->block_aligned_filename_size, &s->src_sg, 1); - if (rc != 1) { + s->block_aligned_filename_size, s->src_sg, 2); + if (rc < 1) { printk(KERN_ERR "%s: Internal error whilst attempting to " - "convert filename memory to scatterlist; " - "expected rc = 1; got rc = [%d]. " + "convert filename memory to scatterlist; rc = [%d]. " "block_aligned_filename_size = [%zd]\n", __func__, rc, s->block_aligned_filename_size); goto out_release_free_unlock; } rc = virt_to_scatterlist(&dest[s->i], s->block_aligned_filename_size, - &s->dst_sg, 1); - if (rc != 1) { + s->dst_sg, 2); + if (rc < 1) { printk(KERN_ERR "%s: Internal error whilst attempting to " "convert encrypted filename memory to scatterlist; " - "expected rc = 1; got rc = [%d]. " - "block_aligned_filename_size = [%zd]\n", __func__, rc, - s->block_aligned_filename_size); + "rc = [%d]. block_aligned_filename_size = [%zd]\n", + __func__, rc, s->block_aligned_filename_size); goto out_release_free_unlock; } /* The characters in the first block effectively do the job @@ -735,7 +733,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, mount_crypt_stat->global_default_fn_cipher_key_bytes); goto out_release_free_unlock; } - rc = crypto_blkcipher_encrypt_iv(&s->desc, &s->dst_sg, &s->src_sg, + rc = crypto_blkcipher_encrypt_iv(&s->desc, s->dst_sg, s->src_sg, s->block_aligned_filename_size); if (rc) { printk(KERN_ERR "%s: Error attempting to encrypt filename; " @@ -767,8 +765,8 @@ struct ecryptfs_parse_tag_70_packet_silly_stack { struct mutex *tfm_mutex; char *decrypted_filename; struct ecryptfs_auth_tok *auth_tok; - struct scatterlist src_sg; - struct scatterlist dst_sg; + struct scatterlist src_sg[2]; + struct scatterlist dst_sg[2]; struct blkcipher_desc desc; char fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX + 1]; char iv[ECRYPTFS_MAX_IV_BYTES]; @@ -873,13 +871,12 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, } mutex_lock(s->tfm_mutex); rc = virt_to_scatterlist(&data[(*packet_size)], - s->block_aligned_filename_size, &s->src_sg, 1); - if (rc != 1) { + s->block_aligned_filename_size, s->src_sg, 2); + if (rc < 1) { printk(KERN_ERR "%s: Internal error whilst attempting to " "convert encrypted filename memory to scatterlist; " - "expected rc = 1; got rc = [%d]. " - "block_aligned_filename_size = [%zd]\n", __func__, rc, - s->block_aligned_filename_size); + "rc = [%d]. block_aligned_filename_size = [%zd]\n", + __func__, rc, s->block_aligned_filename_size); goto out_unlock; } (*packet_size) += s->block_aligned_filename_size; @@ -893,13 +890,12 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, goto out_unlock; } rc = virt_to_scatterlist(s->decrypted_filename, - s->block_aligned_filename_size, &s->dst_sg, 1); - if (rc != 1) { + s->block_aligned_filename_size, s->dst_sg, 2); + if (rc < 1) { printk(KERN_ERR "%s: Internal error whilst attempting to " "convert decrypted filename memory to scatterlist; " - "expected rc = 1; got rc = [%d]. " - "block_aligned_filename_size = [%zd]\n", __func__, rc, - s->block_aligned_filename_size); + "rc = [%d]. block_aligned_filename_size = [%zd]\n", + __func__, rc, s->block_aligned_filename_size); goto out_free_unlock; } /* The characters in the first block effectively do the job of @@ -938,7 +934,7 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, mount_crypt_stat->global_default_fn_cipher_key_bytes); goto out_free_unlock; } - rc = crypto_blkcipher_decrypt_iv(&s->desc, &s->dst_sg, &s->src_sg, + rc = crypto_blkcipher_decrypt_iv(&s->desc, s->dst_sg, s->src_sg, s->block_aligned_filename_size); if (rc) { printk(KERN_ERR "%s: Error attempting to decrypt filename; " -- cgit v1.2.3 From 5b67e307f5e085be7594117b77e61432c13c9c96 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 6 May 2011 17:08:56 +0300 Subject: UBIFS: fix a rare memory leak in ro to rw remounting path commit eaeee242c531cd4b0a4a46e8b5dd7ef504380c42 upstream. When re-mounting from R/O mode to R/W mode and the LEB count in the superblock is not up-to date, because for the underlying UBI volume became larger, we re-write the superblock. We allocate RAM for these purposes, but never free it. So this is a memory leak, although very rare one. Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ubifs/sb.c | 3 ++- fs/ubifs/super.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c index 96cb62c8a9dd..f75f89b7867a 100644 --- a/fs/ubifs/sb.c +++ b/fs/ubifs/sb.c @@ -475,7 +475,8 @@ failed: * @c: UBIFS file-system description object * * This function returns a pointer to the superblock node or a negative error - * code. + * code. Note, the user of this function is responsible of kfree()'ing the + * returned superblock buffer. */ struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c) { diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 4d2f2157dd3f..f4d0c3686d23 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1545,6 +1545,7 @@ static int ubifs_remount_rw(struct ubifs_info *c) } sup->leb_cnt = cpu_to_le32(c->leb_cnt); err = ubifs_write_sb_node(c, sup); + kfree(sup); if (err) goto out; } -- cgit v1.2.3 From 500c1e95d2e4a846025091c8cabee761578fc6cc Mon Sep 17 00:00:00 2001 From: Luca Tettamanti Date: Wed, 25 May 2011 20:43:31 +0200 Subject: i8k: Avoid lahf in 64-bit code commit bc1f419c76a2d6450413ce4349f4e4a07be011d5 upstream. i8k uses lahf to read the flag register in 64-bit code; early x86-64 CPUs, however, lack this instruction and we get an invalid opcode exception at runtime. Use pushf to load the flag register into the stack instead. Signed-off-by: Luca Tettamanti Reported-by: Jeff Rickman Tested-by: Jeff Rickman Tested-by: Harry G McGavran Jr Cc: Massimo Dal Zotto Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/char/i8k.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index 0bd4364fa39d..f830512f5324 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c @@ -138,8 +138,8 @@ static int i8k_smm(struct smm_regs *regs) "movl %%edi,20(%%rax)\n\t" "popq %%rdx\n\t" "movl %%edx,0(%%rax)\n\t" - "lahf\n\t" - "shrl $8,%%eax\n\t" + "pushfq\n\t" + "popq %%rax\n\t" "andl $1,%%eax\n" :"=a"(rc) : "a"(regs) -- cgit v1.2.3 From 857053c1d4fcba46f8fdfcbc4926c1e70757d4a5 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Thu, 24 Feb 2011 17:19:23 +0200 Subject: cpuidle: menu: fixed wrapping timers at 4.294 seconds commit 7467571f4480b273007517b26297c07154c73924 upstream. Cpuidle menu governor is using u32 as a temporary datatype for storing nanosecond values which wrap around at 4.294 seconds. This causes errors in predicted sleep times resulting in higher than should be C state selection and increased power consumption. This also breaks cpuidle state residency statistics. Signed-off-by: Tero Kristo Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/cpuidle/governors/menu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 1b128702d300..fa0787bb8251 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -236,6 +236,7 @@ static int menu_select(struct cpuidle_device *dev) int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); int i; int multiplier; + struct timespec t; if (data->needs_update) { menu_update(dev); @@ -250,8 +251,9 @@ static int menu_select(struct cpuidle_device *dev) return 0; /* determine the expected residency time, round up */ + t = ktime_to_timespec(tick_nohz_get_sleep_length()); data->expected_us = - DIV_ROUND_UP((u32)ktime_to_ns(tick_nohz_get_sleep_length()), 1000); + t.tv_sec * USEC_PER_SEC + t.tv_nsec / NSEC_PER_USEC; data->bucket = which_bucket(data->expected_us); -- cgit v1.2.3 From 1e293bba2a05ab9b38d696c467de02b3b2b45331 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Sun, 29 May 2011 13:02:52 +0100 Subject: dm table: reject devices without request fns commit f4808ca99a203f20b4475601748e44b25a65bdec upstream. This patch adds a check that a block device has a request function defined before it is used. Otherwise, misconfiguration can cause an oops. Because we are allowing devices with zero size e.g. an offline multipath device as in commit 2cd54d9bedb79a97f014e86c0da393416b264eb3 ("dm: allow offline devices") there needs to be an additional check to ensure devices are initialised. Some block devices, like a loop device without a backing file, exist but have no request function. Reproducer is trivial: dm-mirror on unbound loop device (no backing file on loop devices) dmsetup create x --table "0 8 mirror core 2 8 sync 2 /dev/loop0 0 /dev/loop1 0" and mirror resync will immediatelly cause OOps. BUG: unable to handle kernel NULL pointer dereference at (null) ? generic_make_request+0x2bd/0x590 ? kmem_cache_alloc+0xad/0x190 submit_bio+0x53/0xe0 ? bio_add_page+0x3b/0x50 dispatch_io+0x1ca/0x210 [dm_mod] ? read_callback+0x0/0xd0 [dm_mirror] dm_io+0xbb/0x290 [dm_mod] do_mirror+0x1e0/0x748 [dm_mirror] Signed-off-by: Milan Broz Reported-by: Zdenek Kabelac Acked-by: Mike Snitzer Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/md/dm-table.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 4a83321c634d..ebb3864dc9bd 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -352,6 +352,7 @@ static void close_dev(struct dm_dev_internal *d, struct mapped_device *md) static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev, sector_t start, sector_t len, void *data) { + struct request_queue *q; struct queue_limits *limits = data; struct block_device *bdev = dev->bdev; sector_t dev_size = @@ -360,6 +361,22 @@ static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev, limits->logical_block_size >> SECTOR_SHIFT; char b[BDEVNAME_SIZE]; + /* + * Some devices exist without request functions, + * such as loop devices not yet bound to backing files. + * Forbid the use of such devices. + */ + q = bdev_get_queue(bdev); + if (!q || !q->make_request_fn) { + DMWARN("%s: %s is not yet initialised: " + "start=%llu, len=%llu, dev_size=%llu", + dm_device_name(ti->table->md), bdevname(bdev, b), + (unsigned long long)start, + (unsigned long long)len, + (unsigned long long)dev_size); + return 1; + } + if (!dev_size) return 0; -- cgit v1.2.3 From 46fcbe707a5c02e357434409635c759e43d2a665 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 27 May 2011 04:51:54 +0000 Subject: atm: expose ATM device index in sysfs commit e7a46b4d0839c2a3aa2e0ae0b145f293f6738498 upstream. It's currently exposed only through /proc which, besides requiring screen-scraping, doesn't allow userspace to distinguish between two identical ATM adapters with different ATM indexes. The ATM device index is required when using PPPoATM on a system with multiple ATM adapters. Signed-off-by: Dan Williams Reviewed-by: Eric Dumazet Tested-by: David Woodhouse Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/atm/atm_sysfs.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c index 799c631f0fed..67b5bcfbcc7c 100644 --- a/net/atm/atm_sysfs.c +++ b/net/atm/atm_sysfs.c @@ -59,6 +59,14 @@ static ssize_t show_atmaddress(struct device *cdev, return pos - buf; } +static ssize_t show_atmindex(struct device *cdev, + struct device_attribute *attr, char *buf) +{ + struct atm_dev *adev = to_atm_dev(cdev); + + return sprintf(buf, "%d\n", adev->number); +} + static ssize_t show_carrier(struct device *cdev, struct device_attribute *attr, char *buf) { @@ -99,6 +107,7 @@ static ssize_t show_link_rate(struct device *cdev, static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); static DEVICE_ATTR(atmaddress, S_IRUGO, show_atmaddress, NULL); +static DEVICE_ATTR(atmindex, S_IRUGO, show_atmindex, NULL); static DEVICE_ATTR(carrier, S_IRUGO, show_carrier, NULL); static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); static DEVICE_ATTR(link_rate, S_IRUGO, show_link_rate, NULL); @@ -106,6 +115,7 @@ static DEVICE_ATTR(link_rate, S_IRUGO, show_link_rate, NULL); static struct device_attribute *atm_attrs[] = { &dev_attr_atmaddress, &dev_attr_address, + &dev_attr_atmindex, &dev_attr_carrier, &dev_attr_type, &dev_attr_link_rate, -- cgit v1.2.3 From b10337297efbda0eb8ca5f1da53648677791ebb2 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 26 May 2011 21:06:50 +0200 Subject: brd: limit 'max_part' module param to DISK_MAX_PARTS commit 315980c8688c4b06713c1a5fe9d64cdf8ab57a72 upstream. The 'max_part' parameter controls the number of maximum partition a brd device can have. However if a user specifies very large value it would exceed the limitation of device minor number and can cause a kernel panic (or, at least, produce invalid device nodes in some cases). On my desktop system, following command kills the kernel. On qemu, it triggers similar oops but the kernel was alive: $ sudo modprobe brd max_part=100000 BUG: unable to handle kernel NULL pointer dereference at 0000000000000058 IP: [] sysfs_create_dir+0x2d/0xae PGD 7af1067 PUD 7b19067 PMD 0 Oops: 0000 [#1] SMP last sysfs file: CPU 0 Modules linked in: brd(+) Pid: 44, comm: insmod Tainted: G W 2.6.39-qemu+ #158 Bochs Bochs RIP: 0010:[] [] sysfs_create_dir+0x2d/0xae RSP: 0018:ffff880007b15d78 EFLAGS: 00000286 RAX: ffff880007b05478 RBX: ffff880007a52760 RCX: ffff880007b15dc8 RDX: ffff880007a4f900 RSI: ffff880007b15e48 RDI: ffff880007a52760 RBP: ffff880007b15da8 R08: 0000000000000002 R09: 0000000000000000 R10: ffff880007b15e48 R11: ffff880007b05478 R12: 0000000000000000 R13: ffff880007b05478 R14: 0000000000400920 R15: 0000000000000063 FS: 0000000002160880(0063) GS:ffff880007c00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000058 CR3: 0000000007b1c000 CR4: 00000000000006b0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 0000000000000000 DR7: 0000000000000000 Process insmod (pid: 44, threadinfo ffff880007b14000, task ffff880007acb980) Stack: ffff880007b15dc8 ffff880007b05478 ffff880007b15da8 00000000fffffffe ffff880007a52760 ffff880007b05478 ffff880007b15de8 ffffffff81143c0a 0000000000400920 ffff880007a52760 ffff880007b05478 0000000000000000 Call Trace: [] kobject_add_internal+0xdf/0x1a0 [] kobject_add_varg+0x41/0x50 [] kobject_add+0x64/0x66 [] blk_register_queue+0x5f/0xb8 [] add_disk+0xdf/0x289 [] brd_init+0xdf/0x1aa [brd] [] ? 0xffffffffa0003fff [] ? 0xffffffffa0003fff [] do_one_initcall+0x7a/0x12e [] sys_init_module+0x9c/0x1dc [] system_call_fastpath+0x16/0x1b Code: 89 e5 41 55 41 54 53 48 89 fb 48 83 ec 18 48 85 ff 75 04 0f 0b eb fe 48 8b 47 18 49 c7 c4 70 1e 4d 81 48 85 c0 74 04 4c 8b 60 30 8b 44 24 58 45 31 ed 0f b6 c4 85 c0 74 0d 48 8b 43 28 48 89 RIP [] sysfs_create_dir+0x2d/0xae RSP CR2: 0000000000000058 ---[ end trace aebb1175ce1f6739 ]--- Signed-off-by: Namhyung Kim Cc: Laurent Vivier Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/block/brd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/block/brd.c b/drivers/block/brd.c index f1bf79d9bc0a..189d54249bc8 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -582,6 +582,9 @@ static int __init brd_init(void) if (max_part > 0) part_shift = fls(max_part); + if ((1UL << part_shift) > DISK_MAX_PARTS) + return -EINVAL; + if (rd_nr > 1UL << (MINORBITS - part_shift)) return -EINVAL; -- cgit v1.2.3 From 0432b8c1ca35b185997de324b643ac83d554b02c Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 26 May 2011 21:06:50 +0200 Subject: brd: handle on-demand devices correctly commit af46566885a373b0a526932484cd8fef8de7b598 upstream. When finding or allocating a ram disk device, brd_probe() did not take partition numbers into account so that it can result to a different device. Consider following example (I set CONFIG_BLK_DEV_RAM_COUNT=4 for simplicity) : $ sudo modprobe brd max_part=15 $ ls -l /dev/ram* brw-rw---- 1 root disk 1, 0 2011-05-25 15:41 /dev/ram0 brw-rw---- 1 root disk 1, 16 2011-05-25 15:41 /dev/ram1 brw-rw---- 1 root disk 1, 32 2011-05-25 15:41 /dev/ram2 brw-rw---- 1 root disk 1, 48 2011-05-25 15:41 /dev/ram3 $ sudo mknod /dev/ram4 b 1 64 $ sudo dd if=/dev/zero of=/dev/ram4 bs=4k count=256 256+0 records in 256+0 records out 1048576 bytes (1.0 MB) copied, 0.00215578 s, 486 MB/s namhyung@leonhard:linux$ ls -l /dev/ram* brw-rw---- 1 root disk 1, 0 2011-05-25 15:41 /dev/ram0 brw-rw---- 1 root disk 1, 16 2011-05-25 15:41 /dev/ram1 brw-rw---- 1 root disk 1, 32 2011-05-25 15:41 /dev/ram2 brw-rw---- 1 root disk 1, 48 2011-05-25 15:41 /dev/ram3 brw-r--r-- 1 root root 1, 64 2011-05-25 15:45 /dev/ram4 brw-rw---- 1 root disk 1, 1024 2011-05-25 15:44 /dev/ram64 After this patch, /dev/ram4 - instead of /dev/ram64 - was accessed correctly. In addition, 'range' passed to blk_register_region() should include all range of dev_t that RAMDISK_MAJOR can address. It does not need to be limited by partition numbers unless 'rd_nr' param was specified. Signed-off-by: Namhyung Kim Cc: Laurent Vivier Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/block/brd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 189d54249bc8..7b83d0cda1ef 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -549,7 +549,7 @@ static struct kobject *brd_probe(dev_t dev, int *part, void *data) struct kobject *kobj; mutex_lock(&brd_devices_mutex); - brd = brd_init_one(dev & MINORMASK); + brd = brd_init_one(MINOR(dev) >> part_shift); kobj = brd ? get_disk(brd->brd_disk) : ERR_PTR(-ENOMEM); mutex_unlock(&brd_devices_mutex); @@ -590,10 +590,10 @@ static int __init brd_init(void) if (rd_nr) { nr = rd_nr; - range = rd_nr; + range = rd_nr << part_shift; } else { nr = CONFIG_BLK_DEV_RAM_COUNT; - range = 1UL << (MINORBITS - part_shift); + range = 1UL << MINORBITS; } if (register_blkdev(RAMDISK_MAJOR, "ramdisk")) @@ -632,7 +632,7 @@ static void __exit brd_exit(void) unsigned long range; struct brd_device *brd, *next; - range = rd_nr ? rd_nr : 1UL << (MINORBITS - part_shift); + range = rd_nr ? rd_nr << part_shift : 1UL << MINORBITS; list_for_each_entry_safe(brd, next, &brd_devices, brd_list) brd_del_one(brd); -- cgit v1.2.3 From fa895d1e6b22dae5808052facfe11f83fed070ff Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 18 Mar 2011 20:21:23 -0400 Subject: SUNRPC: Deal with the lack of a SYN_SENT sk->sk_state_change callback... commit fe19a96b10032035a35779f42ad59e35d6dd8ffd upstream. The TCP connection state code depends on the state_change() callback being called when the SYN_SENT state is set. However the networking layer doesn't actually call us back in that case. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/sunrpc/xprtsock.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index ce838698723e..eb958197ae62 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1345,7 +1345,6 @@ static void xs_tcp_state_change(struct sock *sk) case TCP_CLOSE_WAIT: /* The server initiated a shutdown of the socket */ xprt_force_disconnect(xprt); - case TCP_SYN_SENT: xprt->connect_cookie++; case TCP_CLOSING: /* @@ -1807,6 +1806,7 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt, struct sock_xprt *tra static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) { struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); + int ret = -ENOTCONN; if (!transport->inet) { struct sock *sk = sock->sk; @@ -1838,12 +1838,22 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) } if (!xprt_bound(xprt)) - return -ENOTCONN; + goto out; /* Tell the socket layer to start connecting... */ xprt->stat.connect_count++; xprt->stat.connect_start = jiffies; - return kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK); + ret = kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK); + switch (ret) { + case 0: + case -EINPROGRESS: + /* SYN_SENT! */ + xprt->connect_cookie++; + if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO) + xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; + } +out: + return ret; } /** -- cgit v1.2.3 From 1c13a3d138b39388108ce6b5b610117da42e0ce2 Mon Sep 17 00:00:00 2001 From: Hemant Pedanekar Date: Tue, 5 Apr 2011 12:32:50 +0530 Subject: PCI: Add quirk for setting valid class for TI816X Endpoint commit 63c4408074cbcc070ac17fc10e524800eb9bd0b0 upstream. TI816X (common name for DM816x/C6A816x/AM389x family) devices configured to boot as PCIe Endpoint have class code = 0. This makes kernel PCI bus code to skip allocating BARs to these devices resulting into following type of error when trying to enable them: "Device 0000:01:00.0 not available because of resource collisions" The device cannot be operated because of the above issue. This patch adds a ID specific (TI VENDOR ID and 816X DEVICE ID based) 'early' fixup quirk to replace class code with PCI_CLASS_MULTIMEDIA_VIDEO as class. Signed-off-by: Hemant Pedanekar Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/pci/quirks.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 06b234f09233..dc42ab666786 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2727,6 +2727,16 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, vtd_mask_spec_errors); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors); #endif +static void __devinit fixup_ti816x_class(struct pci_dev* dev) +{ + /* TI 816x devices do not have class code set when in PCIe boot mode */ + if (dev->class == PCI_CLASS_NOT_DEFINED) { + dev_info(&dev->dev, "Setting PCI class for 816x PCIe device\n"); + dev->class = PCI_CLASS_MULTIMEDIA_VIDEO; + } +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_TI, 0xb800, fixup_ti816x_class); + static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) { -- cgit v1.2.3 From 6f0a1a45a8ed6c59710605fc763a5d3515a4324a Mon Sep 17 00:00:00 2001 From: "Tian, Kevin" Date: Thu, 12 May 2011 10:56:08 +0800 Subject: xen mmu: fix a race window causing leave_mm BUG() commit 7899891c7d161752f29abcc9bc0a9c6c3a3af26c upstream. There's a race window in xen_drop_mm_ref, where remote cpu may exit dirty bitmap between the check on this cpu and the point where remote cpu handles drop request. So in drop_other_mm_ref we need check whether TLB state is still lazy before calling into leave_mm. This bug is rarely observed in earlier kernel, but exaggerated by the commit 831d52bc153971b70e64eccfbed2b232394f22f8 ("x86, mm: avoid possible bogus tlb entries by clearing prev mm_cpumask after switching mm") which clears bitmap after changing the TLB state. the call trace is as below: Signed-off-by: Andi Kleen --------------------------------- kernel BUG at arch/x86/mm/tlb.c:61! invalid opcode: 0000 [#1] SMP last sysfs file: /sys/devices/system/xen_memory/xen_memory0/info/current_kb CPU 1 Modules linked in: 8021q garp xen_netback xen_blkback blktap blkback_pagemap nbd bridge stp llc autofs4 ipmi_devintf ipmi_si ipmi_msghandler lockd sunrpc bonding ipv6 xenfs dm_multipath video output sbs sbshc parport_pc lp parport ses enclosure snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device serio_raw bnx2 snd_pcm_oss snd_mixer_oss snd_pcm snd_timer iTCO_wdt snd soundcore snd_page_alloc i2c_i801 iTCO_vendor_support i2c_core pcs pkr pata_acpi ata_generic ata_piix shpchp mptsas mptscsih mptbase [last unloaded: freq_table] Pid: 25581, comm: khelper Not tainted 2.6.32.36fixxen #1 Tecal RH2285 RIP: e030:[] [] leave_mm+0x15/0x46 RSP: e02b:ffff88002805be48 EFLAGS: 00010046 RAX: 0000000000000000 RBX: 0000000000000001 RCX: ffff88015f8e2da0 RDX: ffff88002805be78 RSI: 0000000000000000 RDI: 0000000000000001 RBP: ffff88002805be48 R08: ffff88009d662000 R09: dead000000200200 R10: dead000000100100 R11: ffffffff814472b2 R12: ffff88009bfc1880 R13: ffff880028063020 R14: 00000000000004f6 R15: 0000000000000000 FS: 00007f62362d66e0(0000) GS:ffff880028058000(0000) knlGS:0000000000000000 CS: e033 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000003aabc11909 CR3: 000000009b8ca000 CR4: 0000000000002660 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 00000000000000 00 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process khelper (pid: 25581, threadinfo ffff88007691e000, task ffff88009b92db40) Stack: ffff88002805be68 ffffffff8100e4ae 0000000000000001 ffff88009d733b88 <0> ffff88002805be98 ffffffff81087224 ffff88002805be78 ffff88002805be78 <0> ffff88015f808360 00000000000004f6 ffff88002805bea8 ffffffff81010108 Call Trace: [] drop_other_mm_ref+0x2a/0x53 [] generic_smp_call_function_single_interrupt+0xd8/0xfc [] xen_call_function_single_interrupt+0x13/0x28 [] handle_IRQ_event+0x66/0x120 [] handle_percpu_irq+0x41/0x6e [] __xen_evtchn_do_upcall+0x1ab/0x27d [] xen_evtchn_do_upcall+0x33/0x46 [] xen_do_hyper visor_callback+0x1e/0x30 [] ? _spin_unlock_irqrestore+0x15/0x17 [] ? xen_restore_fl_direct_end+0x0/0x1 [] ? flush_old_exec+0x3ac/0x500 [] ? load_elf_binary+0x0/0x17ef [] ? load_elf_binary+0x0/0x17ef [] ? load_elf_binary+0x398/0x17ef [] ? need_resched+0x23/0x2d [] ? process_measurement+0xc0/0xd7 [] ? load_elf_binary+0x0/0x17ef [] ? search_binary_handler+0xc8/0x255 [] ? do_execve+0x1c3/0x29e [] ? sys_execve+0x43/0x5d [] ? __call_usermodehelper+0x0/0x6f [] ? kernel_execve+0x68/0xd0 [] ? __call_usermodehelper+0x0/0x6f [] ? xen_restore_fl_direct_end+0x0/0x1 [] ? ____call_usermodehelper+0x113/0x11e [] ? child_rip+0xa/0x20 [] ? __call_usermodehelper+0x0/0x6f [] ? int_ret_from_sys_call+0x7/0x1b [] ? retint_restore_args+0x5/0x6 [] ? child_rip+0x0/0x20 Code: 41 5e 41 5f c9 c3 55 48 89 e5 0f 1f 44 00 00 e8 17 ff ff ff c9 c3 55 48 89 e5 0f 1f 44 00 00 65 8b 04 25 c8 55 01 00 ff c8 75 04 <0f> 0b eb fe 65 48 8b 34 25 c0 55 01 00 48 81 c6 b8 02 00 00 e8 RIP [] leave_mm+0x15/0x46 RSP ---[ end trace ce9cee6832a9c503 ]--- Tested-by: Maoxiaoyun Signed-off-by: Kevin Tian [v1: Fleshed out the git description a bit] Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 6adff931d5f3..4916176c53e3 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1142,7 +1142,7 @@ static void drop_other_mm_ref(void *info) active_mm = percpu_read(cpu_tlbstate.active_mm); - if (active_mm == mm) + if (active_mm == mm && percpu_read(cpu_tlbstate.state) != TLBSTATE_OK) leave_mm(smp_processor_id()); /* If this cpu still has a stale cr3 reference, then make sure -- cgit v1.2.3 From 6093240b06916ca21216bb4728f79b264fd08e30 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 31 May 2011 07:03:21 +0300 Subject: UBIFS: fix shrinker object count reports commit cf610bf4199770420629d3bc273494bd27ad6c1d upstream. Sometimes VM asks the shrinker to return amount of objects it can shrink, and we return the ubifs_clean_zn_cnt in that case. However, it is possible that this counter is negative for a short period of time, due to the way UBIFS TNC code updates it. And I can observe the following warnings sometimes: shrink_slab: ubifs_shrinker+0x0/0x2b7 [ubifs] negative objects to delete nr=-8541616642706119788 This patch makes sure UBIFS never returns negative count of objects. Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ubifs/shrinker.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/ubifs/shrinker.c b/fs/ubifs/shrinker.c index 0b201114a5ad..5306c9195ed8 100644 --- a/fs/ubifs/shrinker.c +++ b/fs/ubifs/shrinker.c @@ -283,7 +283,11 @@ int ubifs_shrinker(struct shrinker *shrink, int nr, gfp_t gfp_mask) long clean_zn_cnt = atomic_long_read(&ubifs_clean_zn_cnt); if (nr == 0) - return clean_zn_cnt; + /* + * Due to the way UBIFS updates the clean znode counter it may + * temporarily be negative. + */ + return clean_zn_cnt >= 0 ? clean_zn_cnt : 1; if (!clean_zn_cnt) { /* -- cgit v1.2.3 From 26543e37c91d678a14a2fcc6795f26f240bcad82 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 31 May 2011 08:40:40 +0300 Subject: UBIFS: fix memory leak on error path commit 812eb258311f89bcd664a34a620f249d54a2cd83 upstream. UBIFS leaks memory on error path in 'ubifs_jnl_update()' in case of write failure because it forgets to free the 'struct ubifs_dent_node *dent' object. Although the object is small, the alignment can make it large - e.g., 2KiB if the min. I/O unit is 2KiB. Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/ubifs/journal.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index d321baeca68d..841f77cc93cf 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -665,6 +665,7 @@ out_free: out_release: release_head(c, BASEHD); + kfree(dent); out_ro: ubifs_ro_mode(c, err); if (last_reference) -- cgit v1.2.3 From 26d4cb6db4636d5d53d22500abb4be201b8fb8e5 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Sat, 28 May 2011 14:44:46 +0200 Subject: nbd: limit module parameters to a sane value commit 3b2710824e00d238554c13b5add347e6c701ab1a upstream. The 'max_part' parameter controls the number of maximum partition a nbd device can have. However if a user specifies very large value it would exceed the limitation of device minor number and can cause a kernel oops (or, at least, produce invalid device nodes in some cases). In addition, specifying large 'nbds_max' value causes same problem for the same reason. On my desktop, following command results to the kernel bug: $ sudo modprobe nbd max_part=100000 kernel BUG at /media/Linux_Data/project/linux/fs/sysfs/group.c:65! invalid opcode: 0000 [#1] SMP last sysfs file: /sys/devices/virtual/block/nbd4/range CPU 1 Modules linked in: nbd(+) bridge stp llc kvm_intel kvm asus_atk0110 sg sr_mod cdrom Pid: 2522, comm: modprobe Tainted: G W 2.6.39-leonard+ #159 System manufacturer System Product Name/P5G41TD-M PRO RIP: 0010:[] [] internal_create_group+0x2f/0x166 RSP: 0018:ffff8801009f1de8 EFLAGS: 00010246 RAX: 00000000ffffffef RBX: ffff880103920478 RCX: 00000000000a7bd3 RDX: ffffffff81a2dbe0 RSI: 0000000000000000 RDI: ffff880103920478 RBP: ffff8801009f1e38 R08: ffff880103920468 R09: ffff880103920478 R10: ffff8801009f1de8 R11: ffff88011eccbb68 R12: ffffffff81a2dbe0 R13: ffff880103920468 R14: 0000000000000000 R15: ffff880103920400 FS: 00007f3c49de9700(0000) GS:ffff88011f800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 00007f3b7fe7c000 CR3: 00000000cd58d000 CR4: 00000000000406e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process modprobe (pid: 2522, threadinfo ffff8801009f0000, task ffff8801009a93a0) Stack: ffff8801009f1e58 ffffffff812e8f6e ffff8801009f1e58 ffffffff812e7a80 ffff880000000010 ffff880103920400 ffff8801002fd0c0 ffff880103920468 0000000000000011 ffff880103920400 ffff8801009f1e48 ffffffff8115ab6a Call Trace: [] ? device_add+0x4f1/0x5e4 [] ? dev_set_name+0x41/0x43 [] sysfs_create_group+0x13/0x15 [] blk_trace_init_sysfs+0x14/0x16 [] blk_register_queue+0x4c/0xfd [] add_disk+0xe4/0x29c [] nbd_init+0x2ab/0x30d [nbd] [] ? 0xffffffffa007dfff [] do_one_initcall+0x7f/0x13e [] sys_init_module+0xa1/0x1e3 [] system_call_fastpath+0x16/0x1b Code: 41 57 41 56 41 55 41 54 53 48 83 ec 28 0f 1f 44 00 00 48 89 fb 41 89 f6 49 89 d4 48 85 ff 74 0b 85 f6 75 0b 48 83 7f 30 00 75 14 <0f> 0b eb fe b9 ea ff ff ff 48 83 7f 30 00 0f 84 09 01 00 00 49 RIP [] internal_create_group+0x2f/0x166 RSP ---[ end trace 753285ffbf72c57c ]--- Signed-off-by: Namhyung Kim Cc: Laurent Vivier Cc: Paul Clements Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/block/nbd.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 218d091f3c52..14046ff3b2d6 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -755,6 +755,12 @@ static int __init nbd_init(void) if (max_part > 0) part_shift = fls(max_part); + if ((1UL << part_shift) > DISK_MAX_PARTS) + return -EINVAL; + + if (nbds_max > 1UL << (MINORBITS - part_shift)) + return -EINVAL; + for (i = 0; i < nbds_max; i++) { struct gendisk *disk = alloc_disk(1 << part_shift); if (!disk) -- cgit v1.2.3 From f253441b14e828b6cb0c8d030d3985738730e5fd Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 27 May 2011 07:44:43 +0200 Subject: block: export blk_{get,put}_queue() commit d86e0e83b32bc84600adb0b6ea1fce389b266682 upstream. We need them in SCSI to fix a bug, but currently they are not exported to modules. Export them. Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- block/blk-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/block/blk-core.c b/block/blk-core.c index f0640d7f800f..3b3affd0885b 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -311,6 +311,7 @@ void blk_unplug_timeout(unsigned long data) trace_block_unplug_timer(q); kblockd_schedule_work(q, &q->unplug_work); } +EXPORT_SYMBOL(blk_put_queue); void blk_unplug(struct request_queue *q) { @@ -640,6 +641,7 @@ int blk_get_queue(struct request_queue *q) return 1; } +EXPORT_SYMBOL(blk_get_queue); static inline void blk_free_request(struct request_queue *q, struct request *rq) { -- cgit v1.2.3 From d4df7c4751eefc0130f4f8bdf396a4ea16876dd4 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 25 May 2011 15:52:14 -0500 Subject: Fix oops caused by queue refcounting failure commit e73e079bf128d68284efedeba1fbbc18d78610f9 upstream. In certain circumstances, we can get an oops from a torn down device. Most notably this is from CD roms trying to call scsi_ioctl. The root cause of the problem is the fact that after scsi_remove_device() has been called, the queue is fully torn down. This is actually wrong since the queue can be used until the sdev release function is called. Therefore, we add an extra reference to the queue which is released in sdev->release, so the queue always exists. Reported-by: Parag Warudkar Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/scsi/scsi_scan.c | 2 +- drivers/scsi/scsi_sysfs.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 1c027a97d8b9..6765188ca816 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -295,7 +295,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, kfree(sdev); goto out; } - + blk_get_queue(sdev->request_queue); sdev->request_queue->queuedata = sdev; scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 2b265a16e92f..0ed2365d04f1 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -319,6 +319,7 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work) kfree(evt); } + blk_put_queue(sdev->request_queue); /* NULL queue means the device can't be used */ sdev->request_queue = NULL; -- cgit v1.2.3 From 03e5ad56ab9cd164f7363a26a56c16c11c3ba758 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Sun, 5 Jun 2011 22:03:13 -0700 Subject: mm: fix ENOSPC returned by handle_mm_fault() commit e0dcd8a05be438b3d2e49ef61441ea3a463663f8 upstream. Al Viro observes that in the hugetlb case, handle_mm_fault() may return a value of the kind ENOSPC when its caller is expecting a value of the kind VM_FAULT_SIGBUS: fix alloc_huge_page()'s failure returns. Signed-off-by: Hugh Dickins Acked-by: Al Viro Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- mm/hugetlb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 54d42b009dbe..00223973b477 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1030,10 +1030,10 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, */ chg = vma_needs_reservation(h, vma, addr); if (chg < 0) - return ERR_PTR(chg); + return ERR_PTR(-VM_FAULT_OOM); if (chg) if (hugetlb_get_quota(inode->i_mapping, chg)) - return ERR_PTR(-ENOSPC); + return ERR_PTR(-VM_FAULT_SIGBUS); spin_lock(&hugetlb_lock); page = dequeue_huge_page_vma(h, vma, addr, avoid_reserve); -- cgit v1.2.3 From e9ca82ad156fc553d935d3e11b63b377c87f92e7 Mon Sep 17 00:00:00 2001 From: "Jordan_Hargrave@Dell.com" Date: Mon, 9 May 2011 15:24:55 -0500 Subject: PCI: Set PCIE maxpayload for card during hotplug insertion commit e522a7126c7c144a1dd14c6f217ac31e71082b1d upstream. The following patch sets the MaxPayload setting to match the parent reading when inserting a PCIE card into a hotplug slot. On our system, the upstream bridge is set to 256, but when inserting a card, the card setting defaults to 128. As soon as I/O is performed to the card it starts receiving errors since the payload size is too small. Reviewed-by: Kenji Kaneshige Signed-off-by: Jordan Hargrave Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/pci/hotplug/pcihp_slot.c | 45 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/pci/hotplug/pcihp_slot.c b/drivers/pci/hotplug/pcihp_slot.c index 80b461c98557..749fdf070319 100644 --- a/drivers/pci/hotplug/pcihp_slot.c +++ b/drivers/pci/hotplug/pcihp_slot.c @@ -158,6 +158,47 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) */ } +/* Program PCIE MaxPayload setting on device: ensure parent maxpayload <= device */ +static int pci_set_payload(struct pci_dev *dev) +{ + int pos, ppos; + u16 pctl, psz; + u16 dctl, dsz, dcap, dmax; + struct pci_dev *parent; + + parent = dev->bus->self; + pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (!pos) + return 0; + + /* Read Device MaxPayload capability and setting */ + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &dctl); + pci_read_config_word(dev, pos + PCI_EXP_DEVCAP, &dcap); + dsz = (dctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5; + dmax = (dcap & PCI_EXP_DEVCAP_PAYLOAD); + + /* Read Parent MaxPayload setting */ + ppos = pci_find_capability(parent, PCI_CAP_ID_EXP); + if (!ppos) + return 0; + pci_read_config_word(parent, ppos + PCI_EXP_DEVCTL, &pctl); + psz = (pctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5; + + /* If parent payload > device max payload -> error + * If parent payload > device payload -> set speed + * If parent payload <= device payload -> do nothing + */ + if (psz > dmax) + return -1; + else if (psz > dsz) { + dev_info(&dev->dev, "Setting MaxPayload to %d\n", 128 << psz); + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, + (dctl & ~PCI_EXP_DEVCTL_PAYLOAD) + + (psz << 5)); + } + return 0; +} + void pci_configure_slot(struct pci_dev *dev) { struct pci_dev *cdev; @@ -169,6 +210,10 @@ void pci_configure_slot(struct pci_dev *dev) (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) return; + ret = pci_set_payload(dev); + if (ret) + dev_warn(&dev->dev, "could not set device max payload\n"); + memset(&hpp, 0, sizeof(hpp)); ret = pci_get_hp_params(dev, &hpp); if (ret) -- cgit v1.2.3 From 0fc485b9d3424421d751d9631ea850a8a6c4cae0 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 19 May 2011 00:43:38 +0300 Subject: nl80211: fix check for valid SSID size in scan operations commit 208c72f4fe44fe09577e7975ba0e7fa0278f3d03 upstream. In both trigger_scan and sched_scan operations, we were checking for the SSID length before assigning the value correctly. Since the memory was just kzalloc'ed, the check was always failing and SSID with over 32 characters were allowed to go through. This was causing a buffer overflow when copying the actual SSID to the proper place. This bug has been there since 2.6.29-rc4. Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/wireless/nl80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index da657d823114..d1f58e5250f6 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3179,12 +3179,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) i = 0; if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) { nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { + request->ssids[i].ssid_len = nla_len(attr); if (request->ssids[i].ssid_len > IEEE80211_MAX_SSID_LEN) { err = -EINVAL; goto out_free; } memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr)); - request->ssids[i].ssid_len = nla_len(attr); i++; } } -- cgit v1.2.3 From d30a7fe49d445fcaf58e1fac46de3f931f37a81d Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 6 Jun 2011 12:32:43 +0200 Subject: lockdep: Fix lock_is_held() on recursion commit f2513cde93f0957d5dc6c09bc24b0cccd27d8e1d upstream. The main lock_is_held() user is lockdep_assert_held(), avoid false assertions in lockdep_off() sections by unconditionally reporting the lock is taken. [ the reason this is important is a lockdep_assert_held() in ttwu() which triggers a warning under lockdep_off() as in printk() which can trigger another wakeup and lock up due to spinlock recursion, as reported and heroically debugged by Arne Jansen ] Reported-and-tested-by: Arne Jansen Signed-off-by: Peter Zijlstra Cc: Linus Torvalds Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/1307398759.2497.966.camel@laptop Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/lockdep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 54286798c37b..e6c932b4ddc6 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -3250,7 +3250,7 @@ int lock_is_held(struct lockdep_map *lock) int ret = 0; if (unlikely(current->lockdep_recursion)) - return ret; + return 1; /* avoid false negative lockdep_assert_held() */ raw_local_irq_save(flags); check_flags(flags); -- cgit v1.2.3 From 80f7f2adfc263a1d9ffcf8435c6bef49f56b2392 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 4 Jun 2011 15:39:21 +0200 Subject: drm/i915: Add a no lvds quirk for the Asus EeeBox PC EB1007 commit 6a574b5b9b186e28abd3e571dfd1700c5220b510 upstream. I found this while figuring out why gnome-shell would not run on my Asus EeeBox PC EB1007. As a standalone "pc" this device cleary does not have an internal panel, yet it claims it does. Add a quirk to fix this. Signed-off-by: Hans de Goede Reviewed-by: Keith Packard Signed-off-by: Keith Packard Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/i915/intel_lvds.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 1266ab39d6dd..4bedcec52288 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -832,6 +832,14 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_PRODUCT_NAME, "U800"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Asus EeeBox PC EB1007", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"), + }, + }, { } /* terminating entry */ }; -- cgit v1.2.3 From ce63e3f96077c6979c9e1e31c5c3abef8c3d9dd9 Mon Sep 17 00:00:00 2001 From: Daniel Haid Date: Wed, 8 Jun 2011 20:04:45 +1000 Subject: drm/radeon/kms: fix for radeon on systems >4GB without hardware iommu commit 62fff811d73095bd95579d72f558f03c78f7914a upstream. On my x86_64 system with >4GB of ram and swiotlb instead of a hardware iommu (because I have a VIA chipset), the call to pci_set_dma_mask (see below) with 40bits returns an error. But it seems that the radeon driver is designed to have need_dma32 = true exactly if pci_set_dma_mask is called with 32 bits and false if it is called with 40 bits. I have read somewhere that the default are 32 bits. So if the call fails I suppose that need_dma32 should be set to true. And indeed the patch fixes the problem I have had before and which I had described here: http://choon.net/forum/read.php?21,106131,115940 Acked-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/gpu/drm/radeon/radeon_device.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index cb5b4ceae7c8..786f5d7cafc8 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -645,6 +645,7 @@ int radeon_device_init(struct radeon_device *rdev, dma_bits = rdev->need_dma32 ? 32 : 40; r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); if (r) { + rdev->need_dma32 = true; printk(KERN_WARNING "radeon: No suitable DMA available.\n"); } -- cgit v1.2.3 From ff7cb9c3fe433028969fe28b5a542a0477b252b3 Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Tue, 31 May 2011 19:38:07 +0900 Subject: fat: Fix corrupt inode flags when remove ATTR_SYS flag commit 1adffbae22332bb558c2a29de19d9aca391869f6 upstream. We are clearly missing '~' in fat_ioctl_set_attributes(). Reported-by: Dmitry Dmitriev Signed-off-by: OGAWA Hirofumi Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/fat/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/fat/file.c b/fs/fat/file.c index 990dfae022e5..f2880571b3b0 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -102,7 +102,7 @@ static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr) if (attr & ATTR_SYS) inode->i_flags |= S_IMMUTABLE; else - inode->i_flags &= S_IMMUTABLE; + inode->i_flags &= ~S_IMMUTABLE; } fat_save_attrs(inode, attr); -- cgit v1.2.3 From ab0cc25a4b0367227df10f18c98db96af2db1dc0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 3 Jun 2011 07:45:28 +0300 Subject: xen: off by one errors in multicalls.c commit f124c6ae59e193705c9ddac57684d50006d710e6 upstream. b->args[] has MC_ARGS elements, so the comparison here should be ">=" instead of ">". Otherwise we read past the end of the array one space. Signed-off-by: Dan Carpenter Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/xen/multicalls.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/x86/xen/multicalls.c b/arch/x86/xen/multicalls.c index 8bff7e7c290b..1b2b73ff0a6e 100644 --- a/arch/x86/xen/multicalls.c +++ b/arch/x86/xen/multicalls.c @@ -189,10 +189,10 @@ struct multicall_space __xen_mc_entry(size_t args) unsigned argidx = roundup(b->argidx, sizeof(u64)); BUG_ON(preemptible()); - BUG_ON(b->argidx > MC_ARGS); + BUG_ON(b->argidx >= MC_ARGS); if (b->mcidx == MC_BATCH || - (argidx + args) > MC_ARGS) { + (argidx + args) >= MC_ARGS) { mc_stats_flush(b->mcidx == MC_BATCH ? FL_SLOTS : FL_ARGS); xen_mc_flush(); argidx = roundup(b->argidx, sizeof(u64)); @@ -206,7 +206,7 @@ struct multicall_space __xen_mc_entry(size_t args) ret.args = &b->args[argidx]; b->argidx = argidx + args; - BUG_ON(b->argidx > MC_ARGS); + BUG_ON(b->argidx >= MC_ARGS); return ret; } @@ -216,7 +216,7 @@ struct multicall_space xen_mc_extend_args(unsigned long op, size_t size) struct multicall_space ret = { NULL, NULL }; BUG_ON(preemptible()); - BUG_ON(b->argidx > MC_ARGS); + BUG_ON(b->argidx >= MC_ARGS); if (b->mcidx == 0) return ret; @@ -224,14 +224,14 @@ struct multicall_space xen_mc_extend_args(unsigned long op, size_t size) if (b->entries[b->mcidx - 1].op != op) return ret; - if ((b->argidx + size) > MC_ARGS) + if ((b->argidx + size) >= MC_ARGS) return ret; ret.mc = &b->entries[b->mcidx - 1]; ret.args = &b->args[b->argidx]; b->argidx += size; - BUG_ON(b->argidx > MC_ARGS); + BUG_ON(b->argidx >= MC_ARGS); return ret; } -- cgit v1.2.3 From 5d8e9bd2745ac9212f5a899471f46bfed2749d42 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 6 Jun 2011 16:04:02 +0200 Subject: x86/amd-iommu: Fix 3 possible endless loops commit 0de66d5b35ee148455e268b2782873204ffdef4b upstream. The driver contains several loops counting on an u16 value where the exit-condition is checked against variables that can have values up to 0xffff. In this case the loops will never exit. This patch fixed 3 such loops. Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/kernel/amd_iommu_init.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 5a170cbbbed8..82cbee9547c7 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -650,8 +650,8 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, { u8 *p = (u8 *)h; u8 *end = p, flags = 0; - u16 dev_i, devid = 0, devid_start = 0, devid_to = 0; - u32 ext_flags = 0; + u16 devid = 0, devid_start = 0, devid_to = 0; + u32 dev_i, ext_flags = 0; bool alias = false; struct ivhd_entry *e; @@ -806,7 +806,7 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, /* Initializes the device->iommu mapping for the driver */ static int __init init_iommu_devices(struct amd_iommu *iommu) { - u16 i; + u32 i; for (i = iommu->first_device; i <= iommu->last_device; ++i) set_iommu_for_device(iommu, i); @@ -1095,7 +1095,7 @@ static int __init init_memory_definitions(struct acpi_table_header *table) */ static void init_device_table(void) { - u16 devid; + u32 devid; for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) { set_dev_entry_bit(devid, DEV_ENTRY_VALID); -- cgit v1.2.3 From 1533b3eed5c2f38caa7a813163ff1f27264077bb Mon Sep 17 00:00:00 2001 From: Toby Gray Date: Mon, 6 Jun 2011 14:52:48 +0100 Subject: USB: cdc-acm: Adding second ACM channel support for Nokia E7 and C7 commit 4061fde2fa80f40cb27114f60500d38d0afcf350 upstream. This adds the Nokia E7 and C7 to the list of devices in cdc-acm, allowing the secondary ACM channel on the device to be exposed. Without this patch the ACM driver won't claim this secondary channel as it's marked as having a vendor-specific protocol. Signed-off-by: Toby Gray Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/class/cdc-acm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 2c70e1e6aa93..851dfb026dcf 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1619,6 +1619,8 @@ static const struct usb_device_id acm_ids[] = { { NOKIA_PCSUITE_ACM_INFO(0x04ce), }, /* Nokia E90 */ { NOKIA_PCSUITE_ACM_INFO(0x01d4), }, /* Nokia E55 */ { NOKIA_PCSUITE_ACM_INFO(0x0302), }, /* Nokia N8 */ + { NOKIA_PCSUITE_ACM_INFO(0x0335), }, /* Nokia E7 */ + { NOKIA_PCSUITE_ACM_INFO(0x03cd), }, /* Nokia C7 */ { SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */ /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ -- cgit v1.2.3 From 98f5adc2ba1389a46cdf0037deb823a672656626 Mon Sep 17 00:00:00 2001 From: Libor Pechacek Date: Fri, 20 May 2011 14:53:25 +0200 Subject: USB: core: Tolerate protocol stall during hub and port status read commit 3824c1ddaf744be44b170a335332b9d6afe79254 upstream. Protocol stall should not be fatal while reading port or hub status as it is transient state. Currently hub EP0 STALL during port status read results in failed device enumeration. This has been observed with ST-Ericsson (formerly Philips) USB 2.0 Hub (04cc:1521) after connecting keyboard. Signed-off-by: Libor Pechacek Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/core/hub.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index d4041c627ff1..d9cdc4a67cbf 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -327,7 +327,8 @@ static int get_hub_status(struct usb_device *hdev, { int i, status = -ETIMEDOUT; - for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) { + for (i = 0; i < USB_STS_RETRIES && + (status == -ETIMEDOUT || status == -EPIPE); i++) { status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0, data, sizeof(*data), USB_STS_TIMEOUT); @@ -343,7 +344,8 @@ static int get_port_status(struct usb_device *hdev, int port1, { int i, status = -ETIMEDOUT; - for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) { + for (i = 0; i < USB_STS_RETRIES && + (status == -ETIMEDOUT || status == -EPIPE); i++) { status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port1, data, sizeof(*data), USB_STS_TIMEOUT); -- cgit v1.2.3 From da619d59095a05bb75792f7133fe53dfaee34df1 Mon Sep 17 00:00:00 2001 From: Steffen Sledz Date: Tue, 7 Jun 2011 14:01:56 +0200 Subject: USB: serial: add another 4N-GALAXY.DE PID to ftdi_sio driver commit a26d31cef06f43a76327c21235e75450869df2b8 upstream. E.g. newer CAN 2.0 A/B <=> USB 2.0 converters report idProduct=f3c2. Signed-off-by: Steffen Sledz Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 3d68c97f9037..943fedd69917 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -646,6 +646,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) }, { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) }, { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_3_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_0_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_1_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_2_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 5eae8251dadc..71694aac4367 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -351,6 +351,7 @@ */ #define FTDI_4N_GALAXY_DE_1_PID 0xF3C0 #define FTDI_4N_GALAXY_DE_2_PID 0xF3C1 +#define FTDI_4N_GALAXY_DE_3_PID 0xF3C2 /* * Linx Technologies product ids -- cgit v1.2.3 From 4cd73ed3097d109d6724e7d475b5e4becdb63bde Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 31 May 2011 14:37:23 -0700 Subject: USB: xhci - fix interval calculation for FS isoc endpoints commit cd3c18ba2fac14b34d03cae111f215009735ea06 upstream. Full-speed isoc endpoints specify interval in exponent based form in frames, not microframes, so we need to adjust accordingly. NEC xHCI host controllers will return an error code of 0x11 if a full speed isochronous endpoint is added with the Interval field set to something less than 3 (2^3 = 8 microframes, or one frame). It is impossible for a full speed device to have an interval smaller than one frame. This was always an issue in the xHCI driver, but commit dfa49c4ad120a784ef1ff0717168aa79f55a483a "USB: xhci - fix math in xhci_get_endpoint_interval()" removed the clamping of the minimum value in the Interval field, which revealed this bug. This needs to be backported to stable kernels back to 2.6.31. Reported-by: Matt Evans Signed-off-by: Dmitry Torokhov Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/xhci-mem.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index fb0a073470d7..648ff8febb30 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -974,9 +974,19 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev, interval = clamp_val(ep->desc.bInterval, 1, 16) - 1; if (interval != ep->desc.bInterval - 1) dev_warn(&udev->dev, - "ep %#x - rounding interval to %d microframes\n", + "ep %#x - rounding interval to %d %sframes\n", ep->desc.bEndpointAddress, - 1 << interval); + 1 << interval, + udev->speed == USB_SPEED_FULL ? "" : "micro"); + + if (udev->speed == USB_SPEED_FULL) { + /* + * Full speed isoc endpoints specify interval in frames, + * not microframes. We are using microframes everywhere, + * so adjust accordingly. + */ + interval += 3; /* 1 frame = 2^3 uframes */ + } return interval; } -- cgit v1.2.3 From bd6b163efb2bb3bb53391778900bfab0877b4647 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Mon, 6 Jun 2011 18:55:34 -0400 Subject: ALSA: hda: Fix quirk for Dell Inspiron 910 commit 0a1896b27b030529ec770aefd790544a1bdb7d5a upstream. BugLink: https://launchpad.net/bugs/792712 The original reporter states that sound from the internal speakers is inaudible until using the model=auto quirk. This symptom is due to an existing quirk mask for 0x102802b* that uses the model=dell quirk. To limit the possible regressions, leave the existing quirk mask but add a higher priority specific mask for the reporter's PCI SSID. Reported-and-tested-by: rodni hipp Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2f06425a2551..73ed47c0b3d1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -13296,6 +13296,7 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = { SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One", ALC268_ACER_ASPIRE_ONE), SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL), + SND_PCI_QUIRK(0x1028, 0x02b0, "Dell Inspiron 910", ALC268_AUTO), SND_PCI_QUIRK_MASK(0x1028, 0xfff0, 0x02b0, "Dell Inspiron Mini9/Vostro A90", ALC268_DELL), /* almost compatible with toshiba but with optional digital outs; -- cgit v1.2.3 From 1a280f789149283526c9e0975bfd36cc70605921 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 31 May 2011 12:35:41 +0200 Subject: oprofile, dcookies: Fix possible circular locking dependency commit fe47ae7f53e179d2ef6771024feb000cbb86640f upstream. The lockdep warning below detects a possible A->B/B->A locking dependency of mm->mmap_sem and dcookie_mutex. The order in sync_buffer() is mm->mmap_sem/dcookie_mutex, while in sys_lookup_dcookie() it is vice versa. Fixing it in sys_lookup_dcookie() by unlocking dcookie_mutex before copy_to_user(). oprofiled/4432 is trying to acquire lock: (&mm->mmap_sem){++++++}, at: [] might_fault+0x53/0xa3 but task is already holding lock: (dcookie_mutex){+.+.+.}, at: [] sys_lookup_dcookie+0x45/0x149 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (dcookie_mutex){+.+.+.}: [] lock_acquire+0xf8/0x11e [] mutex_lock_nested+0x63/0x309 [] get_dcookie+0x30/0x144 [] sync_buffer+0x196/0x3ec [oprofile] [] task_exit_notify+0x16/0x1a [oprofile] [] notifier_call_chain+0x37/0x63 [] __blocking_notifier_call_chain+0x50/0x67 [] blocking_notifier_call_chain+0x14/0x16 [] profile_task_exit+0x1a/0x1c [] do_exit+0x2a/0x6fc [] do_group_exit+0x83/0xae [] sys_exit_group+0x17/0x1b [] system_call_fastpath+0x16/0x1b -> #0 (&mm->mmap_sem){++++++}: [] __lock_acquire+0x1085/0x1711 [] lock_acquire+0xf8/0x11e [] might_fault+0x80/0xa3 [] sys_lookup_dcookie+0x104/0x149 [] system_call_fastpath+0x16/0x1b other info that might help us debug this: 1 lock held by oprofiled/4432: #0: (dcookie_mutex){+.+.+.}, at: [] sys_lookup_dcookie+0x45/0x149 stack backtrace: Pid: 4432, comm: oprofiled Not tainted 2.6.39-00008-ge5a450d #9 Call Trace: [] print_circular_bug+0xae/0xbc [] __lock_acquire+0x1085/0x1711 [] ? get_parent_ip+0x11/0x42 [] ? might_fault+0x53/0xa3 [] lock_acquire+0xf8/0x11e [] ? might_fault+0x53/0xa3 [] ? path_put+0x22/0x27 [] might_fault+0x80/0xa3 [] ? might_fault+0x53/0xa3 [] sys_lookup_dcookie+0x104/0x149 [] system_call_fastpath+0x16/0x1b References: https://bugzilla.kernel.org/show_bug.cgi?id=13809 Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/dcookies.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/dcookies.c b/fs/dcookies.c index a21cabdbd87b..dda0dc702d1b 100644 --- a/fs/dcookies.c +++ b/fs/dcookies.c @@ -178,6 +178,8 @@ SYSCALL_DEFINE(lookup_dcookie)(u64 cookie64, char __user * buf, size_t len) /* FIXME: (deleted) ? */ path = d_path(&dcs->path, kbuf, PAGE_SIZE); + mutex_unlock(&dcookie_mutex); + if (IS_ERR(path)) { err = PTR_ERR(path); goto out_free; @@ -194,6 +196,7 @@ SYSCALL_DEFINE(lookup_dcookie)(u64 cookie64, char __user * buf, size_t len) out_free: kfree(kbuf); + return err; out: mutex_unlock(&dcookie_mutex); return err; -- cgit v1.2.3 From bfac194346ce63ac8a7cec0842a4e65d22f9d708 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 12 Jun 2011 16:35:28 -0400 Subject: CPUFREQ: Remove cpufreq_stats sysfs entries on module unload. commit 13f067537f34456443f61c950cd6dc37d1d5f3ee upstream. cpufreq_stats leaves behind its sysfs entries, which causes a panic when something stumbled across them. (Discovered by unloading cpufreq_stats while powertop was loaded). Signed-off-by: Dave Jones Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/cpufreq/cpufreq_stats.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 4f1b8de2c9f3..7c7a1e481c0d 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -388,6 +388,7 @@ static void __exit cpufreq_stats_exit(void) unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier); for_each_online_cpu(cpu) { cpufreq_stats_free_table(cpu); + cpufreq_stats_free_sysfs(cpu); } } -- cgit v1.2.3 From 8a3c154695b81f55ae4f38b46b86a9db6af73cbc Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 9 Jun 2011 11:42:54 +1000 Subject: md: check ->hot_remove_disk when removing disk commit 01393f3d5836b7d62e925e6f4658a7eb22b83a11 upstream. Check pers->hot_remove_disk instead of pers->hot_add_disk in slot_store() during disk removal. The linear personality only has ->hot_add_disk and no ->hot_remove_disk, so that removing disk in the array resulted to following kernel bug: $ sudo mdadm --create /dev/md0 --level=linear --raid-devices=4 /dev/loop[0-3] $ echo none | sudo tee /sys/block/md0/md/dev-loop2/slot BUG: unable to handle kernel NULL pointer dereference at (null) IP: [< (null)>] (null) PGD c9f5d067 PUD 8575a067 PMD 0 Oops: 0010 [#1] SMP CPU 2 Modules linked in: linear loop bridge stp llc kvm_intel kvm asus_atk0110 sr_mod cdrom sg Pid: 10450, comm: tee Not tainted 3.0.0-rc1-leonard+ #173 System manufacturer System Product Name/P5G41TD-M PRO RIP: 0010:[<0000000000000000>] [< (null)>] (null) RSP: 0018:ffff880085757df0 EFLAGS: 00010282 RAX: ffffffffa00168e0 RBX: ffff8800d1431800 RCX: 000000000000006e RDX: 0000000000000001 RSI: 0000000000000002 RDI: ffff88008543c000 RBP: ffff880085757e48 R08: 0000000000000002 R09: 000000000000000a R10: 0000000000000000 R11: ffff88008543c2e0 R12: 00000000ffffffff R13: ffff8800b4641000 R14: 0000000000000005 R15: 0000000000000000 FS: 00007fe8c9e05700(0000) GS:ffff88011fa00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000000 CR3: 00000000b4502000 CR4: 00000000000406e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process tee (pid: 10450, threadinfo ffff880085756000, task ffff8800c9f08000) Stack: ffffffff8138496a ffff8800b4641000 ffff88008543c268 0000000000000000 ffff8800b4641000 ffff88008543c000 ffff8800d1431868 ffffffff81a78a90 ffff8800b4641000 ffff88008543c000 ffff8800d1431800 ffff880085757e98 Call Trace: [] ? slot_store+0xaa/0x265 [] rdev_attr_store+0x89/0xa8 [] sysfs_write_file+0x108/0x144 [] vfs_write+0xb1/0x10d [] ? trace_hardirqs_on_caller+0x111/0x135 [] sys_write+0x4d/0x77 [] system_call_fastpath+0x16/0x1b Code: Bad RIP value. RIP [< (null)>] (null) RSP CR2: 0000000000000000 ---[ end trace ba5fc64319a826fb ]--- Signed-off-by: Namhyung Kim Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 9ec74cc604f0..010cbdc9506c 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2399,7 +2399,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) if (rdev->raid_disk == -1) return -EEXIST; /* personality does all needed checks */ - if (rdev->mddev->pers->hot_add_disk == NULL) + if (rdev->mddev->pers->hot_remove_disk == NULL) return -EINVAL; err = rdev->mddev->pers-> hot_remove_disk(rdev->mddev, rdev->raid_disk); -- cgit v1.2.3 From f5404e8ba2873b04e010c6cd2750ce8058736386 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 13 Jun 2011 14:48:22 +0900 Subject: md/raid5: fix raid5_set_bi_hw_segments commit 9b2dc8b665932a8e681a7ab3237f60475e75e161 upstream. The @bio->bi_phys_segments consists of active stripes count in the lower 16 bits and processed stripes count in the upper 16 bits. So logical-OR operator should be bitwise one. This bug has been present since 2.6.27 and the fix is suitable for any -stable kernel since then. Fortunately the bad code is only used on error paths and is relatively unlikely to be hit. Signed-off-by: Namhyung Kim Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/md/raid5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 96c690279fc6..8933a3259e14 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -129,7 +129,7 @@ static inline int raid5_dec_bi_hw_segments(struct bio *bio) static inline void raid5_set_bi_hw_segments(struct bio *bio, unsigned int cnt) { - bio->bi_phys_segments = raid5_bi_phys_segments(bio) || (cnt << 16); + bio->bi_phys_segments = raid5_bi_phys_segments(bio) | (cnt << 16); } /* Find first data disk in a raid6 stripe */ -- cgit v1.2.3 From 51f5cfcb1c84031b2fe4b134ae85c36de4b451c8 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Thu, 9 Jun 2011 20:05:18 +0200 Subject: exec: delay address limit change until point of no return commit dac853ae89043f1b7752875300faf614de43c74b upstream. Unconditionally changing the address limit to USER_DS and not restoring it to its old value in the error path is wrong because it prevents us using kernel memory on repeated calls to this function. This, in fact, breaks the fallback of hard coded paths to the init program from being ever successful if the first candidate fails to load. With this patch applied switching to USER_DS is delayed until the point of no return is reached which makes it possible to have a multi-arch rootfs with one arch specific init binary for each of the (hard coded) probed paths. Since the address limit is already set to USER_DS when start_thread() will be invoked, this redundancy can be safely removed. Signed-off-by: Mathias Krause Cc: Al Viro Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/kernel/process_32.c | 1 - arch/x86/kernel/process_64.c | 1 - fs/exec.c | 5 +---- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 8d128783af47..a3d0dc59067b 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -245,7 +245,6 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) { set_user_gs(regs, 0); regs->fs = 0; - set_fs(USER_DS); regs->ds = __USER_DS; regs->es = __USER_DS; regs->ss = __USER_DS; diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 3c2422a99f1f..9cb414381d44 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -337,7 +337,6 @@ start_thread_common(struct pt_regs *regs, unsigned long new_ip, regs->cs = _cs; regs->ss = _ss; regs->flags = X86_EFLAGS_IF; - set_fs(USER_DS); /* * Free the old FP and other extended state */ diff --git a/fs/exec.c b/fs/exec.c index e03ddd4d2a97..34c671e4e4e3 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1024,6 +1024,7 @@ int flush_old_exec(struct linux_binprm * bprm) bprm->mm = NULL; /* We're using it now */ + set_fs(USER_DS); current->flags &= ~PF_RANDOMIZE; flush_thread(); current->personality &= ~bprm->per_clear; @@ -1288,10 +1289,6 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) if (retval) return retval; - /* kernel module loader fixup */ - /* so we don't try to load run modprobe in kernel space. */ - set_fs(USER_DS); - retval = audit_bprm(bprm); if (retval) return retval; -- cgit v1.2.3 From 5ee8f122be3b022ebbfa365c124d541dab5bebbd Mon Sep 17 00:00:00 2001 From: Fernando Luis Vazquez Cao Date: Tue, 10 May 2011 09:55:44 +0200 Subject: netfilter: IPv6: initialize TOS field in REJECT target module commit 4319cc0cf5bb894b7368008cdf6dd20eb8868018 upstream. The IPv6 header is not zeroed out in alloc_skb so we must initialize it properly unless we want to see IPv6 packets with random TOS fields floating around. The current implementation resets the flow label but this could be changed if deemed necessary. We stumbled upon this issue when trying to apply a mangle rule to the RST packet generated by the REJECT target module. Signed-off-by: Fernando Luis Vazquez Cao Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ipv6/netfilter/ip6t_REJECT.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 2933396e0281..d2de57280e76 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c @@ -45,6 +45,8 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) int tcphoff, needs_ack; const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); struct ipv6hdr *ip6h; +#define DEFAULT_TOS_VALUE 0x0U + const __u8 tclass = DEFAULT_TOS_VALUE; struct dst_entry *dst = NULL; u8 proto; struct flowi fl; @@ -123,7 +125,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) skb_put(nskb, sizeof(struct ipv6hdr)); skb_reset_network_header(nskb); ip6h = ipv6_hdr(nskb); - ip6h->version = 6; + *(__be32 *)ip6h = htonl(0x60000000 | (tclass << 20)); ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT); ip6h->nexthdr = IPPROTO_TCP; ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr); -- cgit v1.2.3 From 68b05c3c9f020650fbb69984eefe780bfec80a69 Mon Sep 17 00:00:00 2001 From: Fernando Luis Vazquez Cao Date: Tue, 10 May 2011 10:00:21 +0200 Subject: netfilter: IPv6: fix DSCP mangle code commit 1ed2f73d90fb49bcf5704aee7e9084adb882bfc5 upstream. The mask indicates the bits one wants to zero out, so it needs to be inverted before applying to the original TOS field. Signed-off-by: Fernando Luis Vazquez Cao Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/netfilter/xt_DSCP.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c index 0a229191e55b..ae8271652efa 100644 --- a/net/netfilter/xt_DSCP.c +++ b/net/netfilter/xt_DSCP.c @@ -99,7 +99,7 @@ tos_tg6(struct sk_buff *skb, const struct xt_action_param *par) u_int8_t orig, nv; orig = ipv6_get_dsfield(iph); - nv = (orig & info->tos_mask) ^ info->tos_value; + nv = (orig & ~info->tos_mask) ^ info->tos_value; if (orig != nv) { if (!skb_make_writable(skb, sizeof(struct iphdr))) -- cgit v1.2.3 From 5394cc86a6009e16ca706de9bd05049deedab4b2 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Mon, 1 Nov 2010 16:30:09 +0000 Subject: xen: events: do not unmask event channels on resume commit 6903591f314b8947d0e362bda7715e90eb9df75e upstream. The IRQ core code will take care of disabling and reenabling interrupts over suspend resume automatically, therefore we do not need to do this in the Xen event channel code. The only exception is those event channels marked IRQF_NO_SUSPEND which the IRQ core ignores. We must unmask these ourselves, taking care to obey the current IRQ_DISABLED status. Failure check for IRQ_DISABLED leads to enabling polled only event channels, such as that associated with the pv spinlocks, which must never be enabled: [ 21.970432] ------------[ cut here ]------------ [ 21.970432] kernel BUG at arch/x86/xen/spinlock.c:343! [ 21.970432] invalid opcode: 0000 [#1] SMP [ 21.970432] last sysfs file: /sys/devices/virtual/net/lo/operstate [ 21.970432] Modules linked in: [ 21.970432] [ 21.970432] Pid: 0, comm: swapper Not tainted (2.6.32.24-x86_32p-xen-01034-g787c727 #34) [ 21.970432] EIP: 0061:[] EFLAGS: 00010046 CPU: 3 [ 21.970432] EIP is at dummy_handler+0x3/0x7 [ 21.970432] EAX: 0000021c EBX: dfc16880 ECX: 0000001a EDX: 00000000 [ 21.970432] ESI: dfc02c00 EDI: 00000001 EBP: dfc47e10 ESP: dfc47e10 [ 21.970432] DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0069 [ 21.970432] Process swapper (pid: 0, ti=dfc46000 task=dfc39440 task.ti=dfc46000) [ 21.970432] Stack: [ 21.970432] dfc47e30 c10a39f0 0000021c 00000000 00000000 dfc16880 0000021c 00000001 [ 21.970432] <0> dfc47e40 c10a4f08 0000021c 00000000 dfc47e78 c12240a7 c1839284 c1839284 [ 21.970432] <0> 00000200 00000000 00000000 f5720000 c1f3d028 c1f3d02c 00000180 dfc47e90 [ 21.970432] Call Trace: [ 21.970432] [] ? handle_IRQ_event+0x5f/0x122 [ 21.970432] [] ? handle_percpu_irq+0x2f/0x55 [ 21.970432] [] ? __xen_evtchn_do_upcall+0xdb/0x15f [ 21.970432] [] ? xen_evtchn_do_upcall+0x20/0x30 [ 21.970432] [] ? xen_do_upcall+0x7/0xc [ 21.970432] [] ? apic_reg_read+0xd3/0x22d [ 21.970432] [] ? hypercall_page+0x227/0x1005 [ 21.970432] [] ? xen_force_evtchn_callback+0xf/0x14 [ 21.970432] [] ? check_events+0x8/0xc [ 21.970432] [] ? xen_irq_enable_direct_end+0x0/0x1 [ 21.970432] [] ? finish_task_switch+0x62/0xba [ 21.970432] [] ? schedule+0x808/0x89d [ 21.970432] [] ? hrtimer_start_expires+0x1a/0x22 [ 21.970432] [] ? tick_nohz_restart_sched_tick+0x15a/0x162 [ 21.970432] [] ? cpu_idle+0x6d/0x6f [ 21.970432] [] ? cpu_bringup_and_idle+0xd/0xf [ 21.970432] Code: 5d 0f 95 c0 0f b6 c0 c3 55 66 83 78 02 00 89 e5 5d 0f 95 \ c0 0f b6 c0 c3 55 b2 01 86 10 31 c0 84 d2 89 e5 0f 94 c0 5d c3 55 89 e5 <0f> 0b \ eb fe 55 80 3d 4c ce 84 c1 00 89 e5 57 56 89 c6 53 74 15 [ 21.970432] EIP: [] dummy_handler+0x3/0x7 SS:ESP 0069:dfc47e10 [ 21.970432] ---[ end trace c0b71f7e12cf3011 ]--- Signed-off-by: Ian Campbell Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Stefan Bader Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/xen/events.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 076910891448..9c66deb72b8d 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -819,9 +819,6 @@ static void restore_cpu_virqs(unsigned int cpu) evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_virq_info(evtchn, virq); bind_evtchn_to_cpu(evtchn, cpu); - - /* Ready for use. */ - unmask_evtchn(evtchn); } } @@ -847,10 +844,6 @@ static void restore_cpu_ipis(unsigned int cpu) evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_ipi_info(evtchn, ipi); bind_evtchn_to_cpu(evtchn, cpu); - - /* Ready for use. */ - unmask_evtchn(evtchn); - } } @@ -903,6 +896,7 @@ void xen_poll_irq(int irq) void xen_irq_resume(void) { unsigned int cpu, irq, evtchn; + struct irq_desc *desc; init_evtchn_cpu_bindings(); @@ -921,6 +915,23 @@ void xen_irq_resume(void) restore_cpu_virqs(cpu); restore_cpu_ipis(cpu); } + + /* + * Unmask any IRQF_NO_SUSPEND IRQs which are enabled. These + * are not handled by the IRQ core. + */ + for_each_irq_desc(irq, desc) { + if (!desc->action || !(desc->action->flags & IRQF_NO_SUSPEND)) + continue; + if (desc->status & IRQ_DISABLED) + continue; + + evtchn = evtchn_from_irq(irq); + if (evtchn == -1) + continue; + + unmask_evtchn(evtchn); + } } static struct irq_chip xen_dynamic_chip __read_mostly = { -- cgit v1.2.3 From c2bce5c31e51c5a5852d4c6c84c5cec4f69539e6 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 4 Feb 2011 13:19:20 +0100 Subject: genirq: Add IRQF_FORCE_RESUME commit dc5f219e88294b93009eef946251251ffffb6d60 upstream. Xen needs to reenable interrupts which are marked IRQF_NO_SUSPEND in the resume path. Add a flag to force the reenabling in the resume code. Tested-and-acked-by: Ian Campbell Signed-off-by: Thomas Gleixner Signed-off-by: Stefan Bader Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/linux/interrupt.h | 3 ++- kernel/irq/manage.c | 11 ++++++++++- kernel/irq/pm.c | 3 --- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index a0384a4d1e6f..146712ce7534 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -54,7 +54,7 @@ * Used by threaded interrupts which need to keep the * irq line disabled until the threaded handler has been run. * IRQF_NO_SUSPEND - Do not disable this IRQ during suspend - * + * IRQF_FORCE_RESUME - Force enable it on resume even if IRQF_NO_SUSPEND is set */ #define IRQF_DISABLED 0x00000020 #define IRQF_SAMPLE_RANDOM 0x00000040 @@ -66,6 +66,7 @@ #define IRQF_IRQPOLL 0x00001000 #define IRQF_ONESHOT 0x00002000 #define IRQF_NO_SUSPEND 0x00004000 +#define IRQF_FORCE_RESUME 0x00008000 #define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 6a2281f781c1..a6a8b6af1fe7 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -281,8 +281,17 @@ EXPORT_SYMBOL(disable_irq); void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume) { - if (resume) + if (resume) { + if (!(desc->status & IRQ_SUSPENDED)) { + if (!desc->action) + return; + if (!(desc->action->flags & IRQF_FORCE_RESUME)) + return; + /* Pretend that it got disabled ! */ + desc->depth++; + } desc->status &= ~IRQ_SUSPENDED; + } switch (desc->depth) { case 0: diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c index 0d4005d85b03..d6bfb89cce91 100644 --- a/kernel/irq/pm.c +++ b/kernel/irq/pm.c @@ -53,9 +53,6 @@ void resume_device_irqs(void) for_each_irq_desc(irq, desc) { unsigned long flags; - if (!(desc->status & IRQ_SUSPENDED)) - continue; - raw_spin_lock_irqsave(&desc->lock, flags); __enable_irq(desc, irq, true); raw_spin_unlock_irqrestore(&desc->lock, flags); -- cgit v1.2.3 From 4bd6e30b48fb0c03f9546b711dc86a42fd606aa1 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sat, 5 Feb 2011 20:08:59 +0000 Subject: xen: Use IRQF_FORCE_RESUME commit 676dc3cf5bc36a9e129a3ad8fe3bd7b2ebf20f5d upstream. Mark the IRQF_NO_SUSPEND interrupts IRQF_FORCE_RESUME and remove the extra walk through the interrupt descriptors. Signed-off-by: Thomas Gleixner Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Stefan Bader Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/xen/events.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 9c66deb72b8d..614c88b41f4f 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -537,7 +537,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi, if (irq < 0) return irq; - irqflags |= IRQF_NO_SUSPEND; + irqflags |= IRQF_NO_SUSPEND | IRQF_FORCE_RESUME; retval = request_irq(irq, handler, irqflags, devname, dev_id); if (retval != 0) { unbind_from_irq(irq); @@ -896,7 +896,6 @@ void xen_poll_irq(int irq) void xen_irq_resume(void) { unsigned int cpu, irq, evtchn; - struct irq_desc *desc; init_evtchn_cpu_bindings(); @@ -915,23 +914,6 @@ void xen_irq_resume(void) restore_cpu_virqs(cpu); restore_cpu_ipis(cpu); } - - /* - * Unmask any IRQF_NO_SUSPEND IRQs which are enabled. These - * are not handled by the IRQ core. - */ - for_each_irq_desc(irq, desc) { - if (!desc->action || !(desc->action->flags & IRQF_NO_SUSPEND)) - continue; - if (desc->status & IRQ_DISABLED) - continue; - - evtchn = evtchn_from_irq(irq); - if (evtchn == -1) - continue; - - unmask_evtchn(evtchn); - } } static struct irq_chip xen_dynamic_chip __read_mostly = { -- cgit v1.2.3 From e97ee080621da3c7c393a6f44118e930949e2f9e Mon Sep 17 00:00:00 2001 From: Kasper Pedersen Date: Wed, 20 Oct 2010 15:55:15 -0700 Subject: time: Compensate for rounding on odd-frequency clocksources commit a386b5af8edda1c742ce9f77891e112eefffc005 upstream. When the clocksource is not a multiple of HZ, the clock will be off. For acpi_pm, HZ=1000 the error is 127.111 ppm: The rounding of cycle_interval ends up generating a false error term in ntp_error accumulation since xtime_interval is not exactly 1/HZ. So, we subtract out the error caused by the rounding. This has been visible since 2.6.32-rc2 commit a092ff0f90cae22b2ac8028ecd2c6f6c1a9e4601 time: Implement logarithmic time accumulation That commit raised NTP_INTERVAL_FREQ and exposed the rounding error. testing tool: http://n1.taur.dk/permanent/testpmt.c Also tested with ntpd and a frequency counter. Signed-off-by: Kasper Pedersen Acked-by: john stultz Cc: John Kacur Cc: Clark Williams Cc: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Thomas Gleixner Signed-off-by: Will Tisdale Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/time/timekeeping.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index b87c22f5faf9..f3767c4e42dd 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -32,6 +32,8 @@ struct timekeeper { cycle_t cycle_interval; /* Number of clock shifted nano seconds in one NTP interval. */ u64 xtime_interval; + /* shifted nano seconds left over when rounding cycle_interval */ + s64 xtime_remainder; /* Raw nano seconds accumulated per NTP interval. */ u32 raw_interval; @@ -62,7 +64,7 @@ struct timekeeper timekeeper; static void timekeeper_setup_internals(struct clocksource *clock) { cycle_t interval; - u64 tmp; + u64 tmp, ntpinterval; timekeeper.clock = clock; clock->cycle_last = clock->read(clock); @@ -70,6 +72,7 @@ static void timekeeper_setup_internals(struct clocksource *clock) /* Do the ns -> cycle conversion first, using original mult */ tmp = NTP_INTERVAL_LENGTH; tmp <<= clock->shift; + ntpinterval = tmp; tmp += clock->mult/2; do_div(tmp, clock->mult); if (tmp == 0) @@ -80,6 +83,7 @@ static void timekeeper_setup_internals(struct clocksource *clock) /* Go back from cycles -> shifted ns */ timekeeper.xtime_interval = (u64) interval * clock->mult; + timekeeper.xtime_remainder = ntpinterval - timekeeper.xtime_interval; timekeeper.raw_interval = ((u64) interval * clock->mult) >> clock->shift; @@ -765,7 +769,8 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift) /* Accumulate error between NTP and clock interval */ timekeeper.ntp_error += tick_length << shift; - timekeeper.ntp_error -= timekeeper.xtime_interval << + timekeeper.ntp_error -= + (timekeeper.xtime_interval + timekeeper.xtime_remainder) << (timekeeper.ntp_error_shift + shift); return offset; -- cgit v1.2.3 From a5c70c5bbd56baea711ddd0dfe3e617d0ba20e6f Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 15 Jun 2011 15:08:58 -0700 Subject: ksm: fix NULL pointer dereference in scan_get_next_rmap_item() commit 2b472611a32a72f4a118c069c2d62a1a3f087afd upstream. Andrea Righi reported a case where an exiting task can race against ksmd::scan_get_next_rmap_item (http://lkml.org/lkml/2011/6/1/742) easily triggering a NULL pointer dereference in ksmd. ksm_scan.mm_slot == &ksm_mm_head with only one registered mm CPU 1 (__ksm_exit) CPU 2 (scan_get_next_rmap_item) list_empty() is false lock slot == &ksm_mm_head list_del(slot->mm_list) (list now empty) unlock lock slot = list_entry(slot->mm_list.next) (list is empty, so slot is still ksm_mm_head) unlock slot->mm == NULL ... Oops Close this race by revalidating that the new slot is not simply the list head again. Andrea's test case: #include #include #include #include #define BUFSIZE getpagesize() int main(int argc, char **argv) { void *ptr; if (posix_memalign(&ptr, getpagesize(), BUFSIZE) < 0) { perror("posix_memalign"); exit(1); } if (madvise(ptr, BUFSIZE, MADV_MERGEABLE) < 0) { perror("madvise"); exit(1); } *(char *)NULL = 0; return 0; } Reported-by: Andrea Righi Tested-by: Andrea Righi Cc: Andrea Arcangeli Signed-off-by: Hugh Dickins Signed-off-by: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- mm/ksm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mm/ksm.c b/mm/ksm.c index 79cd773faa85..2db786a576ac 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -1272,6 +1272,12 @@ static struct rmap_item *scan_get_next_rmap_item(struct page **page) slot = list_entry(slot->mm_list.next, struct mm_slot, mm_list); ksm_scan.mm_slot = slot; spin_unlock(&ksm_mmlist_lock); + /* + * Although we tested list_empty() above, a racing __ksm_exit + * of the last mm on the list may have removed it since then. + */ + if (slot == &ksm_mm_head) + return NULL; next_mm: ksm_scan.address = 0; ksm_scan.rmap_list = &slot->rmap_list; -- cgit v1.2.3 From a67f6f3794586c33e430d8a8e61d0548d33a3abe Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Thu, 16 Jun 2011 12:56:19 -0700 Subject: migrate: don't account swapcache as shmem commit 99a15e21d96f6857dafab1e5167e5e8183215c9c upstream. swapcache will reach the below code path in migrate_page_move_mapping, and swapcache is accounted as NR_FILE_PAGES but it's not accounted as NR_SHMEM. Hugh pointed out we must use PageSwapCache instead of comparing mapping to &swapper_space, to avoid build failure with CONFIG_SWAP=n. Signed-off-by: Andrea Arcangeli Acked-by: Hugh Dickins Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- mm/migrate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/migrate.c b/mm/migrate.c index 4205b1d6049e..ca71d064bce7 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -266,7 +266,7 @@ static int migrate_page_move_mapping(struct address_space *mapping, */ __dec_zone_page_state(page, NR_FILE_PAGES); __inc_zone_page_state(newpage, NR_FILE_PAGES); - if (PageSwapBacked(page)) { + if (!PageSwapCache(page) && PageSwapBacked(page)) { __dec_zone_page_state(page, NR_SHMEM); __inc_zone_page_state(newpage, NR_SHMEM); } -- cgit v1.2.3 From e80440bb851ed3378b9855dd2bc9a3763eef48f1 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Fri, 3 Jun 2011 09:51:34 +0000 Subject: xen: partially revert "xen: set max_pfn_mapped to the last pfn mapped" commit a91d92875ee94e4703fd017ccaadb48cfb344994 upstream. We only need to set max_pfn_mapped to the last pfn mapped on x86_64 to make sure that cleanup_highmap doesn't remove important mappings at _end. We don't need to do this on x86_32 because cleanup_highmap is not called on x86_32. Besides lowering max_pfn_mapped on x86_32 has the unwanted side effect of limiting the amount of memory available for the 1:1 kernel pagetable allocation. This patch reverts the x86_32 part of the original patch. Signed-off-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/x86/xen/mmu.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 4916176c53e3..96cdf7806972 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1641,6 +1641,11 @@ static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) for (pteidx = 0; pteidx < PTRS_PER_PTE; pteidx++, pfn++) { pte_t pte; +#ifdef CONFIG_X86_32 + if (pfn > max_pfn_mapped) + max_pfn_mapped = pfn; +#endif + if (!pte_none(pte_page[pteidx])) continue; @@ -1753,7 +1758,9 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, { pmd_t *kernel_pmd; - max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list)); + max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) + + xen_start_info->nr_pt_frames * PAGE_SIZE + + 512*1024); kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd); memcpy(level2_kernel_pgt, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD); -- cgit v1.2.3 From b679fa56258fbe656e5b2f9803fc9918bb703df3 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 16 Jun 2011 16:22:08 +0200 Subject: clocksource: Make watchdog robust vs. interruption commit b5199515c25cca622495eb9c6a8a1d275e775088 upstream. The clocksource watchdog code is interruptible and it has been observed that this can trigger false positives which disable the TSC. The reason is that an interrupt storm or a long running interrupt handler between the read of the watchdog source and the read of the TSC brings the two far enough apart that the delta is larger than the unstable treshold. Move both reads into a short interrupt disabled region to avoid that. Reported-and-tested-by: Vernon Mauery Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/linux/clocksource.h | 1 + kernel/time/clocksource.c | 24 +++++++++++++----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 5ea3c60c160c..b41ee1005726 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -192,6 +192,7 @@ struct clocksource { #ifdef CONFIG_CLOCKSOURCE_WATCHDOG /* Watchdog related data, used by the framework */ struct list_head wd_list; + cycle_t cs_last; cycle_t wd_last; #endif }; diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index c232eebbf7ee..4db1e0adc7d7 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -184,7 +184,6 @@ static struct clocksource *watchdog; static struct timer_list watchdog_timer; static DECLARE_WORK(watchdog_work, clocksource_watchdog_work); static DEFINE_SPINLOCK(watchdog_lock); -static cycle_t watchdog_last; static int watchdog_running; static int clocksource_watchdog_kthread(void *data); @@ -253,11 +252,6 @@ static void clocksource_watchdog(unsigned long data) if (!watchdog_running) goto out; - wdnow = watchdog->read(watchdog); - wd_nsec = clocksource_cyc2ns((wdnow - watchdog_last) & watchdog->mask, - watchdog->mult, watchdog->shift); - watchdog_last = wdnow; - list_for_each_entry(cs, &watchdog_list, wd_list) { /* Clocksource already marked unstable? */ @@ -267,19 +261,28 @@ static void clocksource_watchdog(unsigned long data) continue; } + local_irq_disable(); csnow = cs->read(cs); + wdnow = watchdog->read(watchdog); + local_irq_enable(); /* Clocksource initialized ? */ if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) { cs->flags |= CLOCK_SOURCE_WATCHDOG; - cs->wd_last = csnow; + cs->wd_last = wdnow; + cs->cs_last = csnow; continue; } - /* Check the deviation from the watchdog clocksource. */ - cs_nsec = clocksource_cyc2ns((csnow - cs->wd_last) & + wd_nsec = clocksource_cyc2ns((wdnow - cs->wd_last) & watchdog->mask, + watchdog->mult, watchdog->shift); + + cs_nsec = clocksource_cyc2ns((csnow - cs->cs_last) & cs->mask, cs->mult, cs->shift); - cs->wd_last = csnow; + cs->cs_last = csnow; + cs->wd_last = wdnow; + + /* Check the deviation from the watchdog clocksource. */ if (abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD) { clocksource_unstable(cs, cs_nsec - wd_nsec); continue; @@ -317,7 +320,6 @@ static inline void clocksource_start_watchdog(void) return; init_timer(&watchdog_timer); watchdog_timer.function = clocksource_watchdog; - watchdog_last = watchdog->read(watchdog); watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL; add_timer_on(&watchdog_timer, cpumask_first(cpu_online_mask)); watchdog_running = 1; -- cgit v1.2.3 From fe2a1e38b67ce3138ed85fc7c55a044f0da4d560 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Sun, 5 Jun 2011 23:10:04 -0700 Subject: xhci: Reject double add of active endpoints. commit fa75ac379e63c2864e9049b5e8615e40f65c1e70 upstream. While trying to switch a UAS device from the BOT configuration to the UAS configuration via the bConfigurationValue file, Tanya ran into an issue in the USB core. usb_disable_device() sets entries in udev->ep_out and udev->ep_out to NULL, but doesn't call into the xHCI bandwidth management functions to remove the BOT configuration endpoints from the xHCI host's internal structures. The USB core would then attempt to add endpoints for the UAS configuration, and some of the endpoints had the same address as endpoints in the BOT configuration. The xHCI driver blindly added the endpoints again, but the xHCI host controller rejected the Configure Endpoint command because active endpoints were added without being dropped. Make the xHCI driver reject calls to xhci_add_endpoint() that attempt to add active endpoints without first calling xhci_drop_endpoint(). This should be backported to kernels as old as 2.6.31. Signed-off-by: Sarah Sharp Reported-by: Tanya Brokhman Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/xhci.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 807f8e2366ac..413edadeb86d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1016,6 +1016,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, u32 added_ctxs; unsigned int last_ctx; u32 new_add_flags, new_drop_flags, new_slot_info; + struct xhci_virt_device *virt_dev; int ret = 0; ret = xhci_check_args(hcd, udev, ep, 1, __func__); @@ -1044,11 +1045,25 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, return -EINVAL; } - in_ctx = xhci->devs[udev->slot_id]->in_ctx; - out_ctx = xhci->devs[udev->slot_id]->out_ctx; + virt_dev = xhci->devs[udev->slot_id]; + in_ctx = virt_dev->in_ctx; + out_ctx = virt_dev->out_ctx; ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); ep_index = xhci_get_endpoint_index(&ep->desc); ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); + + /* If this endpoint is already in use, and the upper layers are trying + * to add it again without dropping it, reject the addition. + */ + if (virt_dev->eps[ep_index].ring && + !(le32_to_cpu(ctrl_ctx->drop_flags) & + xhci_get_endpoint_flag(&ep->desc))) { + xhci_warn(xhci, "Trying to add endpoint 0x%x " + "without dropping it.\n", + (unsigned int) ep->desc.bEndpointAddress); + return -EINVAL; + } + /* If the HCD has already noted the endpoint is enabled, * ignore this request. */ @@ -1063,8 +1078,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, * process context, not interrupt context (or so documenation * for usb_set_interface() and usb_set_configuration() claim). */ - if (xhci_endpoint_init(xhci, xhci->devs[udev->slot_id], - udev, ep, GFP_NOIO) < 0) { + if (xhci_endpoint_init(xhci, virt_dev, udev, ep, GFP_NOIO) < 0) { dev_dbg(&udev->dev, "%s - could not initialize ep %#x\n", __func__, ep->desc.bEndpointAddress); return -ENOMEM; -- cgit v1.2.3 From 50a771dfdad39b55910eb18c08c8a789b1281a59 Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Sat, 18 Jun 2011 20:34:01 +0200 Subject: PM: Free memory bitmaps if opening /dev/snapshot fails commit 8440f4b19494467883f8541b7aa28c7bbf6ac92b upstream. When opening /dev/snapshot device, snapshot_open() creates memory bitmaps which are freed in snapshot_release(). But if any of the callbacks called by pm_notifier_call_chain() returns NOTIFY_BAD, open() fails, snapshot_release() is never called and bitmaps are not freed. Next attempt to open /dev/snapshot then triggers BUG_ON() check in create_basic_memory_bitmaps(). This happens e.g. when vmwatchdog module is active on s390x. Signed-off-by: Michal Kubecek Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/power/user.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/power/user.c b/kernel/power/user.c index c36c3b9e8a84..fe4f1ab3f746 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -113,8 +113,10 @@ static int snapshot_open(struct inode *inode, struct file *filp) if (error) pm_notifier_call_chain(PM_POST_RESTORE); } - if (error) + if (error) { + free_basic_memory_bitmaps(); atomic_inc(&snapshot_device_available); + } data->frozen = 0; data->ready = 0; data->platform_support = 0; -- cgit v1.2.3 From 15f13f94ff3e34b02615c339ba77d1b79ba83054 Mon Sep 17 00:00:00 2001 From: "Eugene A. Shatokhin" Date: Tue, 28 Jun 2011 23:04:51 -0400 Subject: ath5k: fix memory leak when fewer than N_PD_CURVES are in use commit a0b8de350be458b33248e48b2174d9af8a4c4798 upstream. We would free the proper number of curves, but in the wrong slots, due to a missing level of indirection through the pdgain_idx table. It's simpler just to try to free all four slots, so do that. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/wireless/ath/ath5k/eeprom.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index ed0263672d6d..487fa4f5db5f 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -1592,14 +1592,12 @@ ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) if (!chinfo[pier].pd_curves) continue; - for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { + for (pdg = 0; pdg < AR5K_EEPROM_N_PD_CURVES; pdg++) { struct ath5k_pdgain_info *pd = &chinfo[pier].pd_curves[pdg]; - if (pd != NULL) { - kfree(pd->pd_step); - kfree(pd->pd_pwr); - } + kfree(pd->pd_step); + kfree(pd->pd_pwr); } kfree(chinfo[pier].pd_curves); -- cgit v1.2.3 From f425cb1dce09680c9790ef49c0aa3f2803f53b64 Mon Sep 17 00:00:00 2001 From: Rafael Aquini Date: Wed, 15 Jun 2011 15:08:39 -0700 Subject: mm: fix negative commitlimit when gigantic hugepages are allocated commit b0320c7b7d1ac1bd5c2d9dff3258524ab39bad32 upstream. When 1GB hugepages are allocated on a system, free(1) reports less available memory than what really is installed in the box. Also, if the total size of hugepages allocated on a system is over half of the total memory size, CommitLimit becomes a negative number. The problem is that gigantic hugepages (order > MAX_ORDER) can only be allocated at boot with bootmem, thus its frames are not accounted to 'totalram_pages'. However, they are accounted to hugetlb_total_pages() What happens to turn CommitLimit into a negative number is this calculation, in fs/proc/meminfo.c: allowed = ((totalram_pages - hugetlb_total_pages()) * sysctl_overcommit_ratio / 100) + total_swap_pages; A similar calculation occurs in __vm_enough_memory() in mm/mmap.c. Also, every vm statistic which depends on 'totalram_pages' will render confusing values, as if system were 'missing' some part of its memory. Impact of this bug: When gigantic hugepages are allocated and sysctl_overcommit_memory == OVERCOMMIT_NEVER. In a such situation, __vm_enough_memory() goes through the mentioned 'allowed' calculation and might end up mistakenly returning -ENOMEM, thus forcing the system to start reclaiming pages earlier than it would be ususal, and this could cause detrimental impact to overall system's performance, depending on the workload. Besides the aforementioned scenario, I can only think of this causing annoyances with memory reports from /proc/meminfo and free(1). [akpm@linux-foundation.org: standardize comment layout] Reported-by: Russ Anderson Signed-off-by: Rafael Aquini Acked-by: Russ Anderson Cc: Andrea Arcangeli Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- mm/hugetlb.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 00223973b477..ffede4d34c69 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1109,6 +1109,14 @@ static void __init gather_bootmem_prealloc(void) WARN_ON(page_count(page) != 1); prep_compound_huge_page(page, h->order); prep_new_huge_page(h, page, page_to_nid(page)); + /* + * If we had gigantic hugepages allocated at boot time, we need + * to restore the 'stolen' pages to totalram_pages in order to + * fix confusing memory reports from free(1) and another + * side-effects, like CommitLimit going negative. + */ + if (h->order > (MAX_ORDER - 1)) + totalram_pages += 1 << h->order; } } -- cgit v1.2.3 From 611fc8078efc615210716abdb7410530ed6616e9 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Tue, 24 May 2011 12:22:03 -0300 Subject: uvcvideo: Remove buffers from the queues when freeing commit 8ca2c80b170c47eeb55f0c2a0f2b8edf85f35d49 upstream. When freeing memory for the video buffers also remove them from the irq & main queues. This fixes an oops when doing the following: open ("/dev/video", ..) VIDIOC_REQBUFS VIDIOC_QBUF VIDIOC_REQBUFS close () As the second VIDIOC_REQBUFS will cause the list entries of the buffers to be cleared while they still hang around on the main and irc queues Signed-off-by: Sjoerd Simons Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/media/video/uvc/uvc_queue.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index 133c78d113ac..8416dd80819e 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -165,6 +165,8 @@ int uvc_free_buffers(struct uvc_video_queue *queue) } if (queue->count) { + uvc_queue_cancel(queue, 0); + INIT_LIST_HEAD(&queue->mainqueue); vfree(queue->mem); queue->count = 0; } -- cgit v1.2.3 From 92a311bf2271b5883e0370f2dee49b5a17f3ee66 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 15 Jun 2011 19:15:23 +0200 Subject: watchdog: mtx1-wdt: request gpio before using it commit 9b19d40aa3ebaf1078779da10555da2ab8512422 upstream. Otherwise, the gpiolib autorequest feature will produce a WARN_ON(): WARNING: at drivers/gpio/gpiolib.c:101 0x8020ec6c() autorequest GPIO-215 [...] Signed-off-by: Florian Fainelli Signed-off-by: Wim Van Sebroeck Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/watchdog/mtx-1_wdt.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index 08e8a6ab74e1..e797a2c797d7 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -211,6 +211,12 @@ static int __devinit mtx1_wdt_probe(struct platform_device *pdev) int ret; mtx1_wdt_device.gpio = pdev->resource[0].start; + ret = gpio_request_one(mtx1_wdt_device.gpio, + GPIOF_OUT_INIT_HIGH, "mtx1-wdt"); + if (ret < 0) { + dev_err(&pdev->dev, "failed to request gpio"); + return ret; + } spin_lock_init(&mtx1_wdt_device.lock); init_completion(&mtx1_wdt_device.stop); @@ -236,6 +242,8 @@ static int __devexit mtx1_wdt_remove(struct platform_device *pdev) mtx1_wdt_device.queue = 0; wait_for_completion(&mtx1_wdt_device.stop); } + + gpio_free(mtx1_wdt_device.gpio); misc_deregister(&mtx1_wdt_misc); return 0; } -- cgit v1.2.3 From df9ceceff3742d28c59093c6c60b3ef1359fdf96 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Sat, 28 May 2011 13:23:42 +0200 Subject: debugobjects: Fix boot crash when kmemleak and debugobjects enabled commit 161b6ae0e067e421b20bb35caf66bdb405c929ac upstream. Order of initialization look like this: ... debugobjects kmemleak ...(lots of other subsystems)... workqueues (through early initcall) ... debugobjects use schedule_work for batch freeing of its data and kmemleak heavily use debugobjects, so when it comes to freeing and workqueues were not initialized yet, kernel crashes: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] __queue_work+0x29/0x41a [] queue_work_on+0x16/0x1d [] queue_work+0x29/0x55 [] schedule_work+0x13/0x15 [] free_object+0x90/0x95 [] debug_check_no_obj_freed+0x187/0x1d3 [] ? _raw_spin_unlock_irqrestore+0x30/0x4d [] ? free_object_rcu+0x68/0x6d [] kmem_cache_free+0x64/0x12c [] free_object_rcu+0x68/0x6d [] __rcu_process_callbacks+0x1b6/0x2d9 ... because system_wq is NULL. Fix it by checking if workqueues susbystem was initialized before using. Signed-off-by: Marcin Slusarz Cc: Catalin Marinas Cc: Tejun Heo Cc: Dipankar Sarma Cc: Paul E. McKenney Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/20110528112342.GA3068@joi.lan Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- lib/debugobjects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/debugobjects.c b/lib/debugobjects.c index deebcc57d4e6..da37f2ca6cc3 100644 --- a/lib/debugobjects.c +++ b/lib/debugobjects.c @@ -198,7 +198,7 @@ static void free_object(struct debug_obj *obj) * initialized: */ if (obj_pool_free > ODEBUG_POOL_SIZE && obj_cache) - sched = !work_pending(&debug_obj_work); + sched = keventd_up() && !work_pending(&debug_obj_work); hlist_add_head(&obj->node, &obj_pool); obj_pool_free++; obj_pool_used--; -- cgit v1.2.3 From cf4ca69d46d49eb6fd8803f6618dd60184892835 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 5 Jun 2011 06:01:13 +0200 Subject: cfq-iosched: fix locking around ioc->ioc_data assignment commit ab4bd22d3cce6977dc039664cc2d052e3147d662 upstream. Since we are modifying this RCU pointer, we need to hold the lock protecting it around it. This fixes a potential reuse and double free of a cfq io_context structure. The bug has been in CFQ for a long time, it hit very few people but those it did hit seemed to see it a lot. Tracked in RH bugzilla here: https://bugzilla.redhat.com/show_bug.cgi?id=577968 Credit goes to Paul Bolle for figuring out that the issue was around the one-hit ioc->ioc_data cache. Thanks to his hard work the issue is now fixed. Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- block/cfq-iosched.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 7982b830db58..46b88948725b 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -2615,8 +2615,11 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd, smp_wmb(); cic->key = cfqd_dead_key(cfqd); - if (ioc->ioc_data == cic) + if (rcu_dereference(ioc->ioc_data) == cic) { + spin_lock(&ioc->lock); rcu_assign_pointer(ioc->ioc_data, NULL); + spin_unlock(&ioc->lock); + } if (cic->cfqq[BLK_RW_ASYNC]) { cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_ASYNC]); -- cgit v1.2.3 From 3cc36915ad70bb028e8b4f748ed4a4e99834e3c0 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 27 Jun 2011 09:03:47 +0200 Subject: cfq-iosched: fix a rcu warning commit 3181faa85bda3dc3f5e630a1846526c9caaa38e3 upstream. I got a rcu warnning at boot. the ioc->ioc_data is rcu_deferenced, but doesn't hold rcu_read_lock. Signed-off-by: Shaohua Li Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- block/cfq-iosched.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 46b88948725b..803ad8be830c 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -2615,11 +2615,14 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd, smp_wmb(); cic->key = cfqd_dead_key(cfqd); + rcu_read_lock(); if (rcu_dereference(ioc->ioc_data) == cic) { + rcu_read_unlock(); spin_lock(&ioc->lock); rcu_assign_pointer(ioc->ioc_data, NULL); spin_unlock(&ioc->lock); - } + } else + rcu_read_unlock(); if (cic->cfqq[BLK_RW_ASYNC]) { cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_ASYNC]); -- cgit v1.2.3 From c2f5b713e6efa93d5af22f6a7a807850023a608b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 29 Jun 2011 11:36:10 +0200 Subject: i2c-taos-evm: Fix log messages commit 9b640f2e154268cb516efcaf9c434f2e73c6783e upstream. * Print all error and information messages even when debugging is disabled. * Don't use adapter device to log messages before it is ready. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/i2c/busses/i2c-taos-evm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c index dd39c1eb03ed..26c352a09298 100644 --- a/drivers/i2c/busses/i2c-taos-evm.c +++ b/drivers/i2c/busses/i2c-taos-evm.c @@ -234,7 +234,7 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv) if (taos->state != TAOS_STATE_IDLE) { err = -ENODEV; - dev_dbg(&serio->dev, "TAOS EVM reset failed (state=%d, " + dev_err(&serio->dev, "TAOS EVM reset failed (state=%d, " "pos=%d)\n", taos->state, taos->pos); goto exit_close; } @@ -255,7 +255,7 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv) msecs_to_jiffies(250)); if (taos->state != TAOS_STATE_IDLE) { err = -ENODEV; - dev_err(&adapter->dev, "Echo off failed " + dev_err(&serio->dev, "TAOS EVM echo off failed " "(state=%d)\n", taos->state); goto exit_close; } @@ -263,7 +263,7 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv) err = i2c_add_adapter(adapter); if (err) goto exit_close; - dev_dbg(&serio->dev, "Connected to TAOS EVM\n"); + dev_info(&serio->dev, "Connected to TAOS EVM\n"); taos->client = taos_instantiate_device(adapter); return 0; @@ -288,7 +288,7 @@ static void taos_disconnect(struct serio *serio) serio_set_drvdata(serio, NULL); kfree(taos); - dev_dbg(&serio->dev, "Disconnected from TAOS EVM\n"); + dev_info(&serio->dev, "Disconnected from TAOS EVM\n"); } static struct serio_device_id taos_serio_ids[] = { -- cgit v1.2.3 From 04bf190d9339a6cd5adef1a4b789517ff9838fdb Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 28 Jun 2011 16:59:42 +1000 Subject: md: avoid endless recovery loop when waiting for fail device to complete. commit 4274215d24633df7302069e51426659d4759c5ed upstream. If a device fails in a way that causes pending request to take a while to complete, md will not be able to immediately remove it from the array in remove_and_add_spares. It will then incorrectly look like a spare device and md will try to recover it even though it is failed. This leads to a recovery process starting and instantly aborting over and over again. We should check if the device is faulty before considering it to be a spare. This will avoid trying to start a recovery that cannot proceed. This bug was introduced in 2.6.26 so that patch is suitable for any kernel since then. Reported-by: Jim Paradis Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/md/md.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index 010cbdc9506c..0f88c4560251 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -6967,6 +6967,7 @@ static int remove_and_add_spares(mddev_t *mddev) list_for_each_entry(rdev, &mddev->disks, same_set) { if (rdev->raid_disk >= 0 && !test_bit(In_sync, &rdev->flags) && + !test_bit(Faulty, &rdev->flags) && !test_bit(Blocked, &rdev->flags)) spares++; if (rdev->raid_disk < 0 -- cgit v1.2.3 From 0d1ae88bf82c77ded2bf12c6e23d3cd7364bb1b4 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 17 Jun 2011 10:14:59 -0400 Subject: SUNRPC: Ensure the RPC client only quits on fatal signals commit 5afa9133cfe67f1bfead6049a9640c9262a7101c upstream. Fix a couple of instances where we were exiting the RPC client on arbitrary signals. We should only do so on fatal signals. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/sunrpc/auth_gss/auth_gss.c | 4 ++-- net/sunrpc/clnt.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 5359f36f6b41..c6fda093afb4 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -575,13 +575,13 @@ retry: } inode = &gss_msg->inode->vfs_inode; for (;;) { - prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE); + prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_KILLABLE); spin_lock(&inode->i_lock); if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) { break; } spin_unlock(&inode->i_lock); - if (signalled()) { + if (fatal_signal_pending(current)) { err = -ERESTARTSYS; goto out_intr; } diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 756fc324db9e..5018acd24137 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -928,7 +928,7 @@ call_allocate(struct rpc_task *task) dprintk("RPC: %5u rpc_buffer allocation failed\n", task->tk_pid); - if (RPC_IS_ASYNC(task) || !signalled()) { + if (RPC_IS_ASYNC(task) || !fatal_signal_pending(current)) { task->tk_action = call_allocate; rpc_delay(task, HZ>>4); return; -- cgit v1.2.3 From 95cb3f2eefee6dd22468318a0d986598f6e9827d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 1 Jul 2011 17:30:00 -0700 Subject: 6pack,mkiss: fix lock inconsistency commit 6e4e2f811bade330126d4029c88c831784a7efd9 upstream. Lockdep found a locking inconsistency in the mkiss_close function: > kernel: [ INFO: inconsistent lock state ] > kernel: 2.6.39.1 #3 > kernel: --------------------------------- > kernel: inconsistent {IN-SOFTIRQ-R} -> {SOFTIRQ-ON-W} usage. > kernel: ax25ipd/2813 [HC0[0]:SC0[0]:HE1:SE1] takes: > kernel: (disc_data_lock){+++?.-}, at: [] mkiss_close+0x1b/0x90 [mkiss] > kernel: {IN-SOFTIRQ-R} state was registered at: The message hints that disc_data_lock is aquired with softirqs disabled, but does not itself disable softirqs, which can in rare circumstances lead to a deadlock. The same problem is present in the 6pack driver, this patch fixes both by using write_lock_bh instead of write_lock. Reported-by: Bernard F6BVP Tested-by: Bernard F6BVP Signed-off-by: Arnd Bergmann Acked-by: Ralf Baechle Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/net/hamradio/6pack.c | 4 ++-- drivers/net/hamradio/mkiss.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 4b52c767ad05..26843e2ac996 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -692,10 +692,10 @@ static void sixpack_close(struct tty_struct *tty) { struct sixpack *sp; - write_lock(&disc_data_lock); + write_lock_bh(&disc_data_lock); sp = tty->disc_data; tty->disc_data = NULL; - write_unlock(&disc_data_lock); + write_unlock_bh(&disc_data_lock); if (!sp) return; diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 66e88bd59caa..bb94407ac8af 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -813,10 +813,10 @@ static void mkiss_close(struct tty_struct *tty) { struct mkiss *ax; - write_lock(&disc_data_lock); + write_lock_bh(&disc_data_lock); ax = tty->disc_data; tty->disc_data = NULL; - write_unlock(&disc_data_lock); + write_unlock_bh(&disc_data_lock); if (!ax) return; -- cgit v1.2.3 From ed5ba3843ac94bee8cd5681ab13645dfc65d3b40 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Mon, 27 Jun 2011 16:18:11 -0700 Subject: taskstats: don't allow duplicate entries in listener mode commit 26c4caea9d697043cc5a458b96411b86d7f6babd upstream. Currently a single process may register exit handlers unlimited times. It may lead to a bloated listeners chain and very slow process terminations. Eg after 10KK sent TASKSTATS_CMD_ATTR_REGISTER_CPUMASKs ~300 Mb of kernel memory is stolen for the handlers chain and "time id" shows 2-7 seconds instead of normal 0.003. It makes it possible to exhaust all kernel memory and to eat much of CPU time by triggerring numerous exits on a single CPU. The patch limits the number of times a single process may register itself on a single CPU to one. One little issue is kept unfixed - as taskstats_exit() is called before exit_files() in do_exit(), the orphaned listener entry (if it was not explicitly deregistered) is kept until the next someone's exit() and implicit deregistration in send_cpu_listeners(). So, if a process registered itself as a listener exits and the next spawned process gets the same pid, it would inherit taskstats attributes. Signed-off-by: Vasiliy Kulikov Cc: Balbir Singh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- kernel/taskstats.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 11281d5792bd..5e21645efde1 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -292,16 +292,18 @@ ret: static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd) { struct listener_list *listeners; - struct listener *s, *tmp; + struct listener *s, *tmp, *s2; unsigned int cpu; if (!cpumask_subset(mask, cpu_possible_mask)) return -EINVAL; + s = NULL; if (isadd == REGISTER) { for_each_cpu(cpu, mask) { - s = kmalloc_node(sizeof(struct listener), GFP_KERNEL, - cpu_to_node(cpu)); + if (!s) + s = kmalloc_node(sizeof(struct listener), + GFP_KERNEL, cpu_to_node(cpu)); if (!s) goto cleanup; s->pid = pid; @@ -310,9 +312,16 @@ static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd) listeners = &per_cpu(listener_array, cpu); down_write(&listeners->sem); + list_for_each_entry_safe(s2, tmp, &listeners->list, list) { + if (s2->pid == pid) + goto next_cpu; + } list_add(&s->list, &listeners->list); + s = NULL; +next_cpu: up_write(&listeners->sem); } + kfree(s); return 0; } -- cgit v1.2.3 From 118c3b3aebbd814bc68c81da3d5de76408a377ad Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 15 Jun 2011 16:27:43 -0400 Subject: USB: don't let errors prevent system sleep commit 0af212ba8f123c2eba151af7726c34a50b127962 upstream. This patch (as1464) implements the recommended policy that most errors during suspend or hibernation should not prevent the system from going to sleep. In particular, failure to suspend a USB driver or a USB device should not prevent the sleep from succeeding: Failure to suspend a device won't matter, because the device will automatically go into suspend mode when the USB bus stops carrying packets. (This might be less true for USB-3.0 devices, but let's not worry about them now.) Failure of a driver to suspend might lead to trouble later on when the system wakes up, but it isn't sufficient reason to prevent the system from going to sleep. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/core/driver.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index a6bd53ace035..d3e71437606f 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1189,13 +1189,22 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) for (i = n - 1; i >= 0; --i) { intf = udev->actconfig->interface[i]; status = usb_suspend_interface(udev, intf, msg); + + /* Ignore errors during system sleep transitions */ + if (!(msg.event & PM_EVENT_AUTO)) + status = 0; if (status != 0) break; } } - if (status == 0) + if (status == 0) { status = usb_suspend_device(udev, msg); + /* Again, ignore errors during system sleep transitions */ + if (!(msg.event & PM_EVENT_AUTO)) + status = 0; + } + /* If the suspend failed, resume interfaces that did get suspended */ if (status != 0) { msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME); -- cgit v1.2.3 From 90e554dbd8bf75807d34126330ec20a36b3c56db Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 15 Jun 2011 16:29:16 -0400 Subject: USB: don't let the hub driver prevent system sleep commit cbb330045e5df8f665ac60227ff898421fc8fb92 upstream. This patch (as1465) continues implementation of the policy that errors during suspend or hibernation should not prevent the system from going to sleep. In this case, failure to turn on the Suspend feature for a hub port shouldn't be reported as an error. There are situations where this does actually occur (such as when the device plugged into that port was disconnected in the recent past), and it turns out to be harmless. There's no reason for it to prevent a system sleep. Also, don't allow the hub driver to fail a system suspend if the downstream ports aren't all suspended. This is also harmless (and should never happen, given the change mentioned above); printing a warning message in the kernel log is all we really need to do. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/core/hub.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index d9cdc4a67cbf..a830339a9f56 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2233,6 +2233,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); + + /* System sleep transitions should never fail */ + if (!(msg.event & PM_EVENT_AUTO)) + status = 0; } else { /* device has up to 10 msec to fully suspend */ dev_dbg(&udev->dev, "usb %ssuspend\n", @@ -2470,16 +2474,15 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) struct usb_device *hdev = hub->hdev; unsigned port1; - /* fail if children aren't already suspended */ + /* Warn if children aren't already suspended */ for (port1 = 1; port1 <= hdev->maxchild; port1++) { struct usb_device *udev; udev = hdev->children [port1-1]; if (udev && udev->can_submit) { - if (!(msg.event & PM_EVENT_AUTO)) - dev_dbg(&intf->dev, "port %d nyet suspended\n", - port1); - return -EBUSY; + dev_warn(&intf->dev, "port %d nyet suspended\n", port1); + if (msg.event & PM_EVENT_AUTO) + return -EBUSY; } } -- cgit v1.2.3 From 8391972fad7fa9ecce49fe70872ca7e3817361b9 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 26 Oct 2010 14:22:19 -0700 Subject: uml: fix CONFIG_STATIC_LINK=y build failure with newer glibc commit aa5fb4dbfd121296ca97c68cf90043a7ea97579d upstream. With glibc 2.11 or later that was built with --enable-multi-arch, the UML link fails with undefined references to __rel_iplt_start and similar symbols. In recent binutils, the default linker script defines these symbols (see ld --verbose). Fix the UML linker scripts to match the new defaults for these sections. Signed-off-by: Roland McGrath Cc: Jeff Dike Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- arch/um/kernel/dyn.lds.S | 14 ++++++++++++-- arch/um/kernel/uml.lds.S | 17 +++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index 69268014dd8e..a3cab6d3ae02 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S @@ -50,8 +50,18 @@ SECTIONS .rela.got : { *(.rela.got) } .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } - .rel.plt : { *(.rel.plt) } - .rela.plt : { *(.rela.plt) } + .rel.plt : { + *(.rel.plt) + PROVIDE_HIDDEN(__rel_iplt_start = .); + *(.rel.iplt) + PROVIDE_HIDDEN(__rel_iplt_end = .); + } + .rela.plt : { + *(.rela.plt) + PROVIDE_HIDDEN(__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN(__rela_iplt_end = .); + } .init : { KEEP (*(.init)) } =0x90909090 diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index 9a873d765615..fbd99402d4d2 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S @@ -43,6 +43,23 @@ SECTIONS __syscall_stub_end = .; } + /* + * These are needed even in a static link, even if they wind up being empty. + * Newer glibc needs these __rel{,a}_iplt_{start,end} symbols. + */ + .rel.plt : { + *(.rel.plt) + PROVIDE_HIDDEN(__rel_iplt_start = .); + *(.rel.iplt) + PROVIDE_HIDDEN(__rel_iplt_end = .); + } + .rela.plt : { + *(.rela.plt) + PROVIDE_HIDDEN(__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN(__rela_iplt_end = .); + } + #include "asm/common.lds.S" init.data : { INIT_DATA } -- cgit v1.2.3 From e892e8ae5702bff1eb6a7ba53d1daa7c9acdc88a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 17 Jun 2011 16:25:39 -0400 Subject: inet_diag: fix inet_diag_bc_audit() [ Upstream commit eeb1497277d6b1a0a34ed36b97e18f2bd7d6de0d ] A malicious user or buggy application can inject code and trigger an infinite loop in inet_diag_bc_audit() Also make sure each instruction is aligned on 4 bytes boundary, to avoid unaligned accesses. Reported-by: Dan Rosenberg Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ipv4/inet_diag.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 7403b9bf1026..99366cbb9948 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -437,7 +437,7 @@ static int valid_cc(const void *bc, int len, int cc) return 0; if (cc == len) return 1; - if (op->yes < 4) + if (op->yes < 4 || op->yes & 3) return 0; len -= op->yes; bc += op->yes; @@ -447,11 +447,11 @@ static int valid_cc(const void *bc, int len, int cc) static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) { - const unsigned char *bc = bytecode; + const void *bc = bytecode; int len = bytecode_len; while (len > 0) { - struct inet_diag_bc_op *op = (struct inet_diag_bc_op *)bc; + const struct inet_diag_bc_op *op = bc; //printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len); switch (op->code) { @@ -462,22 +462,20 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) case INET_DIAG_BC_S_LE: case INET_DIAG_BC_D_GE: case INET_DIAG_BC_D_LE: - if (op->yes < 4 || op->yes > len + 4) - return -EINVAL; case INET_DIAG_BC_JMP: - if (op->no < 4 || op->no > len + 4) + if (op->no < 4 || op->no > len + 4 || op->no & 3) return -EINVAL; if (op->no < len && !valid_cc(bytecode, bytecode_len, len - op->no)) return -EINVAL; break; case INET_DIAG_BC_NOP: - if (op->yes < 4 || op->yes > len + 4) - return -EINVAL; break; default: return -EINVAL; } + if (op->yes < 4 || op->yes > len + 4 || op->yes & 3) + return -EINVAL; bc += op->yes; len -= op->yes; } -- cgit v1.2.3 From ccbd3ac7d060cbed807e2c46239149af716fb666 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 6 Jul 2011 20:15:23 +0200 Subject: PM / Hibernate: Fix free_unnecessary_pages() commit 4d4cf23cdde2f8f9324f5684a7f349e182039529 upstream. There is a bug in free_unnecessary_pages() that causes it to attempt to free too many pages in some cases, which triggers the BUG_ON() in memory_bm_clear_bit() for copy_bm. Namely, if count_data_pages() is initially greater than alloc_normal, we get to_free_normal equal to 0 and "save" greater from 0. In that case, if the sum of "save" and count_highmem_pages() is greater than alloc_highmem, we subtract a positive number from to_free_normal. Hence, since to_free_normal was 0 before the subtraction and is an unsigned int, the result is converted to a huge positive number that is used as the number of pages to free. Fix this bug by checking if to_free_normal is actually greater than or equal to the number we're going to subtract from it. Signed-off-by: Rafael J. Wysocki Signed-off-by: Andi Kleen Reported-and-tested-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- kernel/power/snapshot.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 4d8548da48c5..d0c3c4420eec 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -1199,7 +1199,11 @@ static void free_unnecessary_pages(void) to_free_highmem = alloc_highmem - save; } else { to_free_highmem = 0; - to_free_normal -= save - alloc_highmem; + save -= alloc_highmem; + if (to_free_normal > save) + to_free_normal -= save; + else + to_free_normal = 0; } memory_bm_position_reset(©_bm); -- cgit v1.2.3 From ca62683d3b5f66f89e8b85ff2329cb1794d6c04c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 21 May 2011 07:48:39 +0000 Subject: bug.h: Add WARN_RATELIMIT [ Upstream commit b3eec79b0776e5340a3db75b34953977c7e5086e ] Add a generic mechanism to ratelimit WARN(foo, fmt, ...) messages using a hidden per call site static struct ratelimit_state. Also add an __WARN_RATELIMIT variant to be able to use a specific struct ratelimit_state. Signed-off-by: Joe Perches Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- include/asm-generic/bug.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index c2c9ba032d46..205e167804c4 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -53,6 +53,22 @@ struct bug_entry { #define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0) #endif +#define __WARN_RATELIMIT(condition, state, format...) \ +({ \ + int rtn = 0; \ + if (unlikely(__ratelimit(state))) \ + rtn = WARN(condition, format); \ + rtn; \ +}) + +#define WARN_RATELIMIT(condition, format...) \ +({ \ + static DEFINE_RATELIMIT_STATE(_rs, \ + DEFAULT_RATELIMIT_INTERVAL, \ + DEFAULT_RATELIMIT_BURST); \ + __WARN_RATELIMIT(condition, &_rs, format); \ +}) + /* * WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report * significant issues that need prompt attention if they should ever -- cgit v1.2.3 From 7666ff7ed41d95540caa91717aad005578230a85 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 21 May 2011 07:48:40 +0000 Subject: net: filter: Use WARN_RATELIMIT [ Upstream commit 6c4a5cb219520c7bc937ee186ca53f03733bd09f ] A mis-configured filter can spam the logs with lots of stack traces. Rate-limit the warnings and add printout of the bogus filter information. Original-patch-by: Ben Greear Signed-off-by: Joe Perches Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/core/filter.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/core/filter.c b/net/core/filter.c index 71a433cdf7d3..84df73765598 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -292,7 +292,9 @@ load_b: mem[f_k] = X; continue; default: - WARN_ON(1); + WARN_RATELIMIT(1, "Unknown code:%u jt:%u tf:%u k:%u\n", + fentry->code, fentry->jt, + fentry->jf, fentry->k); return 0; } -- cgit v1.2.3 From 10f5dd7bd3448dd1234d0fee65c73048d244592c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 6 Jun 2011 22:42:06 -0700 Subject: af_packet: prevent information leak [ Upstream commit 13fcb7bd322164c67926ffe272846d4860196dc6 ] In 2.6.27, commit 393e52e33c6c2 (packet: deliver VLAN TCI to userspace) added a small information leak. Add padding field and make sure its zeroed before copy to user. Signed-off-by: Eric Dumazet Signed-off-by: Andi Kleen CC: Patrick McHardy Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/if_packet.h | 2 ++ net/packet/af_packet.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h index 6ac23ef1801a..f1a8005ddfa4 100644 --- a/include/linux/if_packet.h +++ b/include/linux/if_packet.h @@ -61,6 +61,7 @@ struct tpacket_auxdata { __u16 tp_mac; __u16 tp_net; __u16 tp_vlan_tci; + __u16 tp_padding; }; /* Rx ring - header status */ @@ -99,6 +100,7 @@ struct tpacket2_hdr { __u32 tp_sec; __u32 tp_nsec; __u16 tp_vlan_tci; + __u16 tp_padding; }; #define TPACKET2_HDRLEN (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll)) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 2f68bbdd9f50..9742be6d7fc8 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -757,6 +757,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, h.h2->tp_sec = ts.tv_sec; h.h2->tp_nsec = ts.tv_nsec; h.h2->tp_vlan_tci = vlan_tx_tag_get(skb); + h.h2->tp_padding = 0; hdrlen = sizeof(*h.h2); break; default: @@ -1678,6 +1679,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, aux.tp_net = skb_network_offset(skb); aux.tp_vlan_tci = vlan_tx_tag_get(skb); + aux.tp_padding = 0; put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux); } -- cgit v1.2.3 From 22cc5e3a5ba4c4dd731082e05cddfcab0bc456b4 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 1 Jun 2011 21:05:22 -0700 Subject: net/ipv4: Check for mistakenly passed in non-IPv4 address [ Upstream commit d0733d2e29b652b2e7b1438ececa732e4eed98eb ] Check against mistakenly passing in IPv6 addresses (which would result in an INADDR_ANY bind) or similar incompatible sockaddrs. Signed-off-by: Marcus Meissner Cc: Reinhard Max Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ipv4/af_inet.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 551ce564b035..5c1bdde9e299 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -464,6 +464,9 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (addr_len < sizeof(struct sockaddr_in)) goto out; + if (addr->sin_family != AF_INET) + goto out; + chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr); /* Not specified by any standard per-se, however it breaks too -- cgit v1.2.3 From f5e8deec38218b6c2c20b546dd7727640d68d8f5 Mon Sep 17 00:00:00 2001 From: Xufeng Zhang Date: Tue, 21 Jun 2011 10:43:39 +0000 Subject: ipv6/udp: Use the correct variable to determine non-blocking condition [ Upstream commit 32c90254ed4a0c698caa0794ebb4de63fcc69631 ] udpv6_recvmsg() function is not using the correct variable to determine whether or not the socket is in non-blocking operation, this will lead to unexpected behavior when a UDP checksum error occurs. Consider a non-blocking udp receive scenario: when udpv6_recvmsg() is called by sock_common_recvmsg(), MSG_DONTWAIT bit of flags variable in udpv6_recvmsg() is cleared by "flags & ~MSG_DONTWAIT" in this call: err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT, flags & ~MSG_DONTWAIT, &addr_len); i.e. with udpv6_recvmsg() getting these values: int noblock = flags & MSG_DONTWAIT int flags = flags & ~MSG_DONTWAIT So, when udp checksum error occurs, the execution will go to csum_copy_err, and then the problem happens: csum_copy_err: ............... if (flags & MSG_DONTWAIT) return -EAGAIN; goto try_again; ............... But it will always go to try_again as MSG_DONTWAIT has been cleared from flags at call time -- only noblock contains the original value of MSG_DONTWAIT, so the test should be: if (noblock) return -EAGAIN; This is also consistent with what the ipv4/udp code does. Signed-off-by: Xufeng Zhang Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ipv6/udp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 97e1214d7ff9..e49cf67506e8 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -445,7 +445,7 @@ csum_copy_err: } unlock_sock_fast(sk, slow); - if (flags & MSG_DONTWAIT) + if (noblock) return -EAGAIN; goto try_again; } -- cgit v1.2.3 From cc51d661483c95a61b5385e70e56af019059bde8 Mon Sep 17 00:00:00 2001 From: Xufeng Zhang Date: Tue, 21 Jun 2011 10:43:40 +0000 Subject: udp/recvmsg: Clear MSG_TRUNC flag when starting over for a new packet [ Upstream commit 9cfaa8def1c795a512bc04f2aec333b03724ca2e ] Consider this scenario: When the size of the first received udp packet is bigger than the receive buffer, MSG_TRUNC bit is set in msg->msg_flags. However, if checksum error happens and this is a blocking socket, it will goto try_again loop to receive the next packet. But if the size of the next udp packet is smaller than receive buffer, MSG_TRUNC flag should not be set, but because MSG_TRUNC bit is not cleared in msg->msg_flags before receive the next packet, MSG_TRUNC is still set, which is wrong. Fix this problem by clearing MSG_TRUNC flag when starting over for a new packet. Signed-off-by: Xufeng Zhang Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- net/ipv4/udp.c | 3 +++ net/ipv6/udp.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index f0fbbba1d203..43536dc8b954 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1206,6 +1206,9 @@ csum_copy_err: if (noblock) return -EAGAIN; + + /* starting over for a new packet */ + msg->msg_flags &= ~MSG_TRUNC; goto try_again; } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index e49cf67506e8..af1a88502d07 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -447,6 +447,9 @@ csum_copy_err: if (noblock) return -EAGAIN; + + /* starting over for a new packet */ + msg->msg_flags &= ~MSG_TRUNC; goto try_again; } -- cgit v1.2.3 From 2d32f62fbbad8f663c26df23242113ef9464f790 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Wed, 23 Feb 2011 13:49:47 +0100 Subject: mm: prevent concurrent unmap_mapping_range() on the same inode commit 2aa15890f3c191326678f1bd68af61ec6b8753ec upstream. Michael Leun reported that running parallel opens on a fuse filesystem can trigger a "kernel BUG at mm/truncate.c:475" Gurudas Pai reported the same bug on NFS. The reason is, unmap_mapping_range() is not prepared for more than one concurrent invocation per inode. For example: thread1: going through a big range, stops in the middle of a vma and stores the restart address in vm_truncate_count. thread2: comes in with a small (e.g. single page) unmap request on the same vma, somewhere before restart_address, finds that the vma was already unmapped up to the restart address and happily returns without doing anything. Another scenario would be two big unmap requests, both having to restart the unmapping and each one setting vm_truncate_count to its own value. This could go on forever without any of them being able to finish. Truncate and hole punching already serialize with i_mutex. Other callers of unmap_mapping_range() do not, and it's difficult to get i_mutex protection for all callers. In particular ->d_revalidate(), which calls invalidate_inode_pages2_range() in fuse, may be called with or without i_mutex. This patch adds a new mutex to 'struct address_space' to prevent running multiple concurrent unmap_mapping_range() on the same mapping. [ We'll hopefully get rid of all this with the upcoming mm preemptibility series by Peter Zijlstra, the "mm: Remove i_mmap_mutex lockbreak" patch in particular. But that is for 2.6.39 ] Signed-off-by: Miklos Szeredi Reported-by: Michael Leun Reported-by: Gurudas Pai Tested-by: Gurudas Pai Acked-by: Hugh Dickins Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- fs/inode.c | 22 +++++++++++++++------- fs/nilfs2/btnode.c | 13 ------------- fs/nilfs2/btnode.h | 1 - fs/nilfs2/super.c | 2 +- include/linux/fs.h | 2 ++ mm/memory.c | 2 ++ 6 files changed, 20 insertions(+), 22 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index 722860b323a9..a4c0bf5dbf93 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -245,6 +245,20 @@ void destroy_inode(struct inode *inode) kmem_cache_free(inode_cachep, (inode)); } +void address_space_init_once(struct address_space *mapping) +{ + memset(mapping, 0, sizeof(*mapping)); + INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC); + spin_lock_init(&mapping->tree_lock); + spin_lock_init(&mapping->i_mmap_lock); + INIT_LIST_HEAD(&mapping->private_list); + spin_lock_init(&mapping->private_lock); + INIT_RAW_PRIO_TREE_ROOT(&mapping->i_mmap); + INIT_LIST_HEAD(&mapping->i_mmap_nonlinear); + mutex_init(&mapping->unmap_mutex); +} +EXPORT_SYMBOL(address_space_init_once); + /* * These are initializations that only need to be done * once, because the fields are idempotent across use @@ -256,13 +270,7 @@ void inode_init_once(struct inode *inode) INIT_HLIST_NODE(&inode->i_hash); INIT_LIST_HEAD(&inode->i_dentry); INIT_LIST_HEAD(&inode->i_devices); - INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC); - spin_lock_init(&inode->i_data.tree_lock); - spin_lock_init(&inode->i_data.i_mmap_lock); - INIT_LIST_HEAD(&inode->i_data.private_list); - spin_lock_init(&inode->i_data.private_lock); - INIT_RAW_PRIO_TREE_ROOT(&inode->i_data.i_mmap); - INIT_LIST_HEAD(&inode->i_data.i_mmap_nonlinear); + address_space_init_once(&inode->i_data); i_size_ordered_init(inode); #ifdef CONFIG_INOTIFY INIT_LIST_HEAD(&inode->inotify_watches); diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c index 447ce47a3306..7133a6145cfe 100644 --- a/fs/nilfs2/btnode.c +++ b/fs/nilfs2/btnode.c @@ -35,19 +35,6 @@ #include "btnode.h" -void nilfs_btnode_cache_init_once(struct address_space *btnc) -{ - memset(btnc, 0, sizeof(*btnc)); - INIT_RADIX_TREE(&btnc->page_tree, GFP_ATOMIC); - spin_lock_init(&btnc->tree_lock); - INIT_LIST_HEAD(&btnc->private_list); - spin_lock_init(&btnc->private_lock); - - spin_lock_init(&btnc->i_mmap_lock); - INIT_RAW_PRIO_TREE_ROOT(&btnc->i_mmap); - INIT_LIST_HEAD(&btnc->i_mmap_nonlinear); -} - static const struct address_space_operations def_btnode_aops = { .sync_page = block_sync_page, }; diff --git a/fs/nilfs2/btnode.h b/fs/nilfs2/btnode.h index 07da83f07712..fa2f1e68f4d1 100644 --- a/fs/nilfs2/btnode.h +++ b/fs/nilfs2/btnode.h @@ -37,7 +37,6 @@ struct nilfs_btnode_chkey_ctxt { struct buffer_head *newbh; }; -void nilfs_btnode_cache_init_once(struct address_space *); void nilfs_btnode_cache_init(struct address_space *, struct backing_dev_info *); void nilfs_btnode_cache_clear(struct address_space *); struct buffer_head *nilfs_btnode_create_block(struct address_space *btnc, diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index fbb354c36e69..79542d014e02 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -1120,7 +1120,7 @@ static void nilfs_inode_init_once(void *obj) #ifdef CONFIG_NILFS_XATTR init_rwsem(&ii->xattr_sem); #endif - nilfs_btnode_cache_init_once(&ii->i_btnode_cache); + address_space_init_once(&ii->i_btnode_cache); ii->i_bmap = (struct nilfs_bmap *)&ii->i_bmap_union; inode_init_once(&ii->vfs_inode); } diff --git a/include/linux/fs.h b/include/linux/fs.h index 509ca14a42c5..af089d5ad700 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -639,6 +639,7 @@ struct address_space { spinlock_t private_lock; /* for use by the address_space */ struct list_head private_list; /* ditto */ struct address_space *assoc_mapping; /* ditto */ + struct mutex unmap_mutex; /* to protect unmapping */ } __attribute__((aligned(sizeof(long)))); /* * On most architectures that alignment is already the case; but @@ -2160,6 +2161,7 @@ extern loff_t vfs_llseek(struct file *file, loff_t offset, int origin); extern int inode_init_always(struct super_block *, struct inode *); extern void inode_init_once(struct inode *); +extern void address_space_init_once(struct address_space *mapping); extern void inode_add_to_lists(struct super_block *, struct inode *); extern void iput(struct inode *); extern struct inode * igrab(struct inode *); diff --git a/mm/memory.c b/mm/memory.c index 7550758d26f8..e85fd5ab3d48 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2573,6 +2573,7 @@ void unmap_mapping_range(struct address_space *mapping, details.last_index = ULONG_MAX; details.i_mmap_lock = &mapping->i_mmap_lock; + mutex_lock(&mapping->unmap_mutex); spin_lock(&mapping->i_mmap_lock); /* Protect against endless unmapping loops */ @@ -2589,6 +2590,7 @@ void unmap_mapping_range(struct address_space *mapping, if (unlikely(!list_empty(&mapping->i_mmap_nonlinear))) unmap_mapping_range_list(&mapping->i_mmap_nonlinear, &details); spin_unlock(&mapping->i_mmap_lock); + mutex_unlock(&mapping->unmap_mutex); } EXPORT_SYMBOL(unmap_mapping_range); -- cgit v1.2.3 From 658a3f90a819379393ff18d97a28b55ae8ed6328 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Fri, 24 Jun 2011 16:08:38 +0400 Subject: proc: restrict access to /proc/PID/io [ upstream commit 1d1221f375c94ef961ba8574ac4f85c8870ddd51 ] /proc/PID/io may be used for gathering private information. E.g. for openssh and vsftpd daemons wchars/rchars may be used to learn the precise password length. Restrict it to processes being able to ptrace the target process. ptrace_may_access() is needed to prevent keeping open file descriptor of "io" file, executing setuid binary and gathering io information of the setuid'ed process. Said to be CVE-2011-2495 Signed-off-by: Vasiliy Kulikov Signed-off-by: Linus Torvalds Signed-off-by: Andi Kleen --- fs/proc/base.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index d073b90f5dc6..c410e23ecd79 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2514,6 +2514,9 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole) struct task_io_accounting acct = task->ioac; unsigned long flags; + if (!ptrace_may_access(task, PTRACE_MODE_READ)) + return -EACCES; + if (whole && lock_task_sighand(task, &flags)) { struct task_struct *t = task; @@ -2636,7 +2639,7 @@ static const struct pid_entry tgid_base_stuff[] = { REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations), #endif #ifdef CONFIG_TASK_IO_ACCOUNTING - INF("io", S_IRUGO, proc_tgid_io_accounting), + INF("io", S_IRUSR, proc_tgid_io_accounting), #endif }; @@ -2972,7 +2975,7 @@ static const struct pid_entry tid_base_stuff[] = { REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), #endif #ifdef CONFIG_TASK_IO_ACCOUNTING - INF("io", S_IRUGO, proc_tid_io_accounting), + INF("io", S_IRUSR, proc_tid_io_accounting), #endif }; -- cgit v1.2.3 From 5c118168c852e64bc273ad62b63b773cd58a4efc Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 15 Jun 2011 15:09:01 -0700 Subject: alpha: fix several security issues [ upstream commit 21c5977a836e399fc710ff2c5367845ed5c2527f ] Fix several security issues in Alpha-specific syscalls. Untested, but mostly trivial. 1. Signedness issue in osf_getdomainname allows copying out-of-bounds kernel memory to userland. 2. Signedness issue in osf_sysinfo allows copying large amounts of kernel memory to userland. 3. Typo (?) in osf_getsysinfo bounds minimum instead of maximum copy size, allowing copying large amounts of kernel memory to userland. 4. Usage of user pointer in osf_wait4 while under KERNEL_DS allows privilege escalation via writing return value of sys_wait4 to kernel memory. Said to fix CVE-2011-2208 to CVE-2011-2211 Signed-off-by: Dan Rosenberg Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Matt Turner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Andi Kleen --- arch/alpha/kernel/osf_sys.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index de9d39717808..57825bbaf27f 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -432,7 +432,7 @@ SYSCALL_DEFINE2(osf_getdomainname, char __user *, name, int, namelen) return -EFAULT; len = namelen; - if (namelen > 32) + if (len > 32) len = 32; down_read(&uts_sem); @@ -619,7 +619,7 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count) down_read(&uts_sem); res = sysinfo_table[offset]; len = strlen(res)+1; - if (len > count) + if ((unsigned long)len > (unsigned long)count) len = count; if (copy_to_user(buf, res, len)) err = -EFAULT; @@ -674,7 +674,7 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer, return 1; case GSI_GET_HWRPB: - if (nbytes < sizeof(*hwrpb)) + if (nbytes > sizeof(*hwrpb)) return -EINVAL; if (copy_to_user(buffer, hwrpb, nbytes) != 0) return -EFAULT; @@ -1036,6 +1036,7 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options, { struct rusage r; long ret, err; + unsigned int status = 0; mm_segment_t old_fs; if (!ur) @@ -1044,13 +1045,15 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options, old_fs = get_fs(); set_fs (KERNEL_DS); - ret = sys_wait4(pid, ustatus, options, (struct rusage __user *) &r); + ret = sys_wait4(pid, (unsigned int __user *) &status, options, + (struct rusage __user *) &r); set_fs (old_fs); if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur))) return -EFAULT; err = 0; + err |= put_user(status, ustatus); err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec); err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec); err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec); -- cgit v1.2.3 From d05d43cd875bb21f94fd39d814e05d6ac3e8baa8 Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Fri, 13 May 2011 09:04:59 +0800 Subject: x86: Make Dell Latitude E5420 use reboot=pci [ upstream commit b7798d28ec15d20fd34b70fa57eb13f0cf6d1ecd ] Rebooting on the Dell E5420 often hangs with the keyboard or ACPI methods, but is reliable via the PCI method. [ hpa: this was deferred because we believed for a long time that the recent reshuffling of the boot priorities in commit 660e34cebf0a11d54f2d5dd8838607452355f321 fixed this platform. Unfortunately that turned out to be incorrect. ] Signed-off-by: Daniel J Blueman Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/1305248699-2347-1-git-send-email-daniel.blueman@gmail.com Signed-off-by: H. Peter Anvin Cc: --- arch/x86/kernel/reboot.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 76a0d715a031..d91d3f22abb2 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -477,6 +477,14 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"), }, }, + { /* Handle problems with rebooting on the Latitude E5420. */ + .callback = set_pci_reboot, + .ident = "Dell Latitude E5420", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5420"), + }, + }, { } }; -- cgit v1.2.3 From 76a1fd83341756986f8c317109aff4ac3d27ba97 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 21 Jul 2011 11:22:21 -0700 Subject: x86: Make Dell Latitude E6420 use reboot=pci [ upstream commit a536877e77f73ea22d12d94a019fedd9671b6acd ] Yet another variant of the Dell Latitude series which requires reboot=pci. From the E5420 bug report by Daniel J Blueman: > The E6420 is affected also (same platform, different casing and > features), which provides an external confirmation of the issue; I can > submit a patch for that later or include it if you prefer: > http://linux.koolsolutions.com/2009/08/04/howto-fix-linux-hangfreeze-during-reboots-and-restarts/ Reported-by: Daniel J Blueman Signed-off-by: H. Peter Anvin Cc: Signed-off-by: Andi Kleen --- arch/x86/kernel/reboot.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index d91d3f22abb2..807e3c98bbbf 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -485,6 +485,14 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5420"), }, }, + { /* Handle problems with rebooting on the Latitude E6420. */ + .callback = set_pci_reboot, + .ident = "Dell Latitude E6420", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6420"), + }, + }, { } }; -- cgit v1.2.3 From 444442d989e4b1fe12527ffa0d94d582177194da Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 25 Jul 2011 17:12:32 -0700 Subject: mm/futex: fix futex writes on archs with SW tracking of [ upstream commit 2efaca927f5cd7ecd0f1554b8f9b6a9a2c329c03 ] dirty & young I haven't reproduced it myself but the fail scenario is that on such machines (notably ARM and some embedded powerpc), if you manage to hit that futex path on a writable page whose dirty bit has gone from the PTE, you'll livelock inside the kernel from what I can tell. It will go in a loop of trying the atomic access, failing, trying gup to "fix it up", getting succcess from gup, go back to the atomic access, failing again because dirty wasn't fixed etc... So I think you essentially hang in the kernel. The scenario is probably rare'ish because affected architecture are embedded and tend to not swap much (if at all) so we probably rarely hit the case where dirty is missing or young is missing, but I think Shan has a piece of SW that can reliably reproduce it using a shared writable mapping & fork or something like that. On archs who use SW tracking of dirty & young, a page without dirty is effectively mapped read-only and a page without young unaccessible in the PTE. Additionally, some architectures might lazily flush the TLB when relaxing write protection (by doing only a local flush), and expect a fault to invalidate the stale entry if it's still present on another processor. The futex code assumes that if the "in_atomic()" access -EFAULT's, it can "fix it up" by causing get_user_pages() which would then be equivalent to taking the fault. However that isn't the case. get_user_pages() will not call handle_mm_fault() in the case where the PTE seems to have the right permissions, regardless of the dirty and young state. It will eventually update those bits ... in the struct page, but not in the PTE. Additionally, it will not handle the lazy TLB flushing that can be required by some architectures in the fault case. Basically, gup is the wrong interface for the job. The patch provides a more appropriate one which boils down to just calling handle_mm_fault() since what we are trying to do is simulate a real page fault. The futex code currently attempts to write to user memory within a pagefault disabled section, and if that fails, tries to fix it up using get_user_pages(). This doesn't work on archs where the dirty and young bits are maintained by software, since they will gate access permission in the TLB, and will not be updated by gup(). In addition, there's an expectation on some archs that a spurious write fault triggers a local TLB flush, and that is missing from the picture as well. I decided that adding those "features" to gup() would be too much for this already too complex function, and instead added a new simpler fixup_user_fault() which is essentially a wrapper around handle_mm_fault() which the futex code can call. [akpm@linux-foundation.org: coding-style fixes] [akpm@linux-foundation.org: fix some nits Darren saw, fiddle comment layout] Signed-off-by: Benjamin Herrenschmidt Reported-by: Shan Hai Tested-by: Shan Hai Cc: David Laight Acked-by: Peter Zijlstra Cc: Darren Hart Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Andi Kleen --- include/linux/mm.h | 2 ++ kernel/futex.c | 4 ++-- mm/memory.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index a724d896a38f..334b4375e82b 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -850,6 +850,8 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, int get_user_pages_fast(unsigned long start, int nr_pages, int write, struct page **pages); struct page *get_dump_page(unsigned long addr); +extern int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm, + unsigned long address, unsigned int fault_flags); extern int try_to_release_page(struct page * page, gfp_t gfp_mask); extern void do_invalidatepage(struct page *page, unsigned long offset); diff --git a/kernel/futex.c b/kernel/futex.c index e328f574c97c..185ee68a6d18 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -306,8 +306,8 @@ static int fault_in_user_writeable(u32 __user *uaddr) int ret; down_read(&mm->mmap_sem); - ret = get_user_pages(current, mm, (unsigned long)uaddr, - 1, 1, 0, NULL, NULL); + ret = fixup_user_fault(current, mm, (unsigned long)uaddr, + FAULT_FLAG_WRITE); up_read(&mm->mmap_sem); return ret < 0 ? ret : 0; diff --git a/mm/memory.c b/mm/memory.c index e85fd5ab3d48..4b12a10baecf 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1497,7 +1497,63 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, return i; } -/** +/* + * fixup_user_fault() - manually resolve a user page fault + * @tsk: the task_struct to use for page fault accounting, or + * NULL if faults are not to be recorded. + * @mm: mm_struct of target mm + * @address: user address + * @fault_flags:flags to pass down to handle_mm_fault() + * + * This is meant to be called in the specific scenario where for locking reasons + * we try to access user memory in atomic context (within a pagefault_disable() + * section), this returns -EFAULT, and we want to resolve the user fault before + * trying again. + * + * Typically this is meant to be used by the futex code. + * + * The main difference with get_user_pages() is that this function will + * unconditionally call handle_mm_fault() which will in turn perform all the + * necessary SW fixup of the dirty and young bits in the PTE, while + * handle_mm_fault() only guarantees to update these in the struct page. + * + * This is important for some architectures where those bits also gate the + * access permission to the page because they are maintained in software. On + * such architectures, gup() will not be enough to make a subsequent access + * succeed. + * + * This should be called with the mm_sem held for read. + */ +int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm, + unsigned long address, unsigned int fault_flags) +{ + struct vm_area_struct *vma; + int ret; + + vma = find_extend_vma(mm, address); + if (!vma || address < vma->vm_start) + return -EFAULT; + + ret = handle_mm_fault(mm, vma, address, fault_flags); + if (ret & VM_FAULT_ERROR) { + if (ret & VM_FAULT_OOM) + return -ENOMEM; + if (ret & VM_FAULT_HWPOISON) + return -EFAULT; + if (ret & VM_FAULT_SIGBUS) + return -EFAULT; + BUG(); + } + if (tsk) { + if (ret & VM_FAULT_MAJOR) + tsk->maj_flt++; + else + tsk->min_flt++; + } + return 0; +} + +/* * get_user_pages() - pin user pages in memory * @tsk: task_struct of target task * @mm: mm_struct of target mm -- cgit v1.2.3 From 6b1ffd2fa340aca8687ec0d1795c0be19f72a29c Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 25 Jul 2011 17:11:57 -0700 Subject: mm/backing-dev.c: reset bdi min_ratio in bdi_unregister() [ upstream commit ccb6108f5b0b541d3eb332c3a73e645c0f84278e ] Vito said: : The system has many usb disks coming and going day to day, with their : respective bdi's having min_ratio set to 1 when inserted. It works for : some time until eventually min_ratio can no longer be set, even when the : active set of bdi's seen in /sys/class/bdi/*/min_ratio doesn't add up to : anywhere near 100. : : This then leads to an unrelated starvation problem caused by write-heavy : fuse mounts being used atop the usb disks, a problem the min_ratio setting : at the underlying devices bdi effectively prevents. Fix this leakage by resetting the bdi min_ratio when unregistering the BDI. Signed-off-by: Peter Zijlstra Reported-by: Vito Caputo Cc: Wu Fengguang Cc: Miklos Szeredi Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Andi Kleen --- mm/backing-dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/backing-dev.c b/mm/backing-dev.c index c0f715719829..3f2b8d037c98 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -646,6 +646,7 @@ static void bdi_prune_sb(struct backing_dev_info *bdi) void bdi_unregister(struct backing_dev_info *bdi) { if (bdi->dev) { + bdi_set_min_ratio(bdi, 0); bdi_prune_sb(bdi); if (!bdi_cap_flush_forker(bdi)) -- cgit v1.2.3 From ef8b14b4fd36fbf79a7823b5741fa901755ee62d Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Mon, 25 Jul 2011 17:11:53 -0700 Subject: xtensa: prevent arbitrary read in ptrace [ upstream commit 0d0138ebe24b94065580bd2601f8bb7eb6152f56 ] Prevent an arbitrary kernel read. Check the user pointer with access_ok() before copying data in. [akpm@linux-foundation.org: s/EIO/EFAULT/] Signed-off-by: Dan Rosenberg Cc: Christian Zankel Cc: Oleg Nesterov Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Andi Kleen --- arch/xtensa/kernel/ptrace.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index 9d4e1ceb3f09..f0ccfc763461 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c @@ -147,6 +147,9 @@ int ptrace_setxregs(struct task_struct *child, void __user *uregs) elf_xtregs_t *xtregs = uregs; int ret = 0; + if (!access_ok(VERIFY_READ, uregs, sizeof(elf_xtregs_t))) + return -EFAULT; + #if XTENSA_HAVE_COPROCESSORS /* Flush all coprocessors before we overwrite them. */ coprocessor_flush_all(ti); -- cgit v1.2.3 From ef652fd1d50af7236399055d621051aafffd1789 Mon Sep 17 00:00:00 2001 From: Manfred Spraul Date: Mon, 25 Jul 2011 17:11:47 -0700 Subject: ipc/sem.c: fix race with concurrent semtimedop() timeouts [ upstream commit d694ad62bf539dbb20a0899ac2a954555f9e4a83 ] and IPC_RMID If a semaphore array is removed and in parallel a sleeping task is woken up (signal or timeout, does not matter), then the woken up task does not wait until wake_up_sem_queue_do() is completed. This will cause crashes, because wake_up_sem_queue_do() will read from a stale pointer. The fix is simple: Regardless of anything, always call get_queue_result(). This function waits until wake_up_sem_queue_do() has finished it's task. Addresses https://bugzilla.kernel.org/show_bug.cgi?id=27142 Reported-by: Yuriy Yevtukhov Reported-by: Harald Laabs Signed-off-by: Manfred Spraul Acked-by: Eric Dumazet Cc: [2.6.35+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Andi Kleen --- ipc/sem.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/ipc/sem.c b/ipc/sem.c index 40a8f462a822..09860766aa57 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1452,15 +1452,24 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, } sma = sem_lock(ns, semid); + + /* + * Wait until it's guaranteed that no wakeup_sem_queue_do() is ongoing. + */ + error = get_queue_result(&queue); + + /* + * Array removed? If yes, leave without sem_unlock(). + */ if (IS_ERR(sma)) { error = -EIDRM; goto out_free; } - error = get_queue_result(&queue); /* - * If queue.status != -EINTR we are woken up by another process + * If queue.status != -EINTR we are woken up by another process. + * Leave without unlink_queue(), but with sem_unlock(). */ if (error != -EINTR) { -- cgit v1.2.3 From 1cbddbe0d078aa1dd9445ee421caaceec90ef914 Mon Sep 17 00:00:00 2001 From: Guo-Fu Tseng Date: Wed, 20 Jul 2011 16:57:36 +0000 Subject: jme: Fix unmap error (Causing system freeze) [ upstream commit 94c5b41b327e08de0ddf563237855f55080652a1 ] This patch add the missing dma_unmap(). Which solved the critical issue of system freeze on heavy load. Michal Miroslaw's rejected patch: [PATCH v2 10/46] net: jme: convert to generic DMA API Pointed out the issue also, thank you Michal. But the fix was incorrect. It would unmap needed address when low memory. Got lots of feedback from End user and Gentoo Bugzilla. https://bugs.gentoo.org/show_bug.cgi?id=373109 Thank you all. :) Cc: stable@kernel.org Signed-off-by: Guo-Fu Tseng Acked-by: Chris Wright Signed-off-by: David S. Miller Signed-off-by: Andi Kleen --- drivers/net/jme.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/net/jme.c b/drivers/net/jme.c index f0643ac4aff1..0d0aafd2444d 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -678,20 +678,28 @@ jme_make_new_rx_buf(struct jme_adapter *jme, int i) struct jme_ring *rxring = &(jme->rxring[0]); struct jme_buffer_info *rxbi = rxring->bufinf + i; struct sk_buff *skb; + dma_addr_t mapping; skb = netdev_alloc_skb(jme->dev, jme->dev->mtu + RX_EXTRA_LEN); if (unlikely(!skb)) return -ENOMEM; + mapping = pci_map_page(jme->pdev, virt_to_page(skb->data), + offset_in_page(skb->data), skb_tailroom(skb), + PCI_DMA_FROMDEVICE); + if (unlikely(pci_dma_mapping_error(jme->pdev, mapping))) { + dev_kfree_skb(skb); + return -ENOMEM; + } + + if (likely(rxbi->mapping)) + pci_unmap_page(jme->pdev, rxbi->mapping, + rxbi->len, PCI_DMA_FROMDEVICE); + rxbi->skb = skb; rxbi->len = skb_tailroom(skb); - rxbi->mapping = pci_map_page(jme->pdev, - virt_to_page(skb->data), - offset_in_page(skb->data), - rxbi->len, - PCI_DMA_FROMDEVICE); - + rxbi->mapping = mapping; return 0; } -- cgit v1.2.3 From 300896911157016b30ea6f2de8705b675441e76a Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 7 Jul 2011 15:45:40 -0500 Subject: fix crash in scsi_dispatch_cmd() [ upstream commit bfe159a51203c15d23cb3158fffdc25ec4b4dda1 ] USB surprise removal of sr is triggering an oops in scsi_dispatch_command(). What seems to be happening is that USB is hanging on to a queue reference until the last close of the upper device, so the crash is caused by surprise remove of a mounted CD followed by attempted unmount. The problem is that USB doesn't issue its final commands as part of the SCSI teardown path, but on last close when the block queue is long gone. The long term fix is probably to make sr do the teardown in the same way as sd (so remove all the lower bits on ejection, but keep the upper disk alive until last close of user space). However, the current oops can be simply fixed by not allowing any commands to be sent to a dead queue. Cc: stable@kernel.org Signed-off-by: James Bottomley Signed-off-by: Andi Kleen --- block/blk-core.c | 3 +++ block/blk-exec.c | 7 +++++++ drivers/scsi/scsi_lib.c | 2 ++ 3 files changed, 12 insertions(+) diff --git a/block/blk-core.c b/block/blk-core.c index 3b3affd0885b..1818a05d53b8 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -893,6 +893,9 @@ struct request *blk_get_request(struct request_queue *q, int rw, gfp_t gfp_mask) { struct request *rq; + if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) + return NULL; + BUG_ON(rw != READ && rw != WRITE); spin_lock_irq(q->queue_lock); diff --git a/block/blk-exec.c b/block/blk-exec.c index 49557e91f0da..85bd7b445d86 100644 --- a/block/blk-exec.c +++ b/block/blk-exec.c @@ -50,6 +50,13 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, { int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; + if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) { + rq->errors = -ENXIO; + if (rq->end_io) + rq->end_io(rq, rq->errors); + return; + } + rq->rq_disk = bd_disk; rq->end_io = done; WARN_ON(irqs_disabled()); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 725f3cdcedcf..56034eecc6e7 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -215,6 +215,8 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, int ret = DRIVER_ERROR << 24; req = blk_get_request(sdev->request_queue, write, __GFP_WAIT); + if (!req) + return ret; if (bufflen && blk_rq_map_kern(sdev->request_queue, req, buffer, bufflen, __GFP_WAIT)) -- cgit v1.2.3 From afd392409785398ec6b3b2e3ac7c8510aff02ae3 Mon Sep 17 00:00:00 2001 From: Manoj Iyer Date: Thu, 26 May 2011 11:19:05 -0500 Subject: mmc: Add PCI fixup quirks for Ricoh 1180:e823 reader [ upstream commit be98ca652faa6468916a9b7608befff215a8ca70 ] Signed-off-by: Manoj Iyer Cc: Signed-off-by: Chris Ball Signed-off-by: Andi Kleen --- drivers/pci/quirks.c | 2 ++ include/linux/pci_ids.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index dc42ab666786..19a81cf2b61f 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2701,6 +2701,8 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE823, ricoh_mmc_fixup_r5c832); +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE823, ricoh_mmc_fixup_r5c832); #endif /*CONFIG_MMC_RICOH_MMC*/ #if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f1cbd85ad5ec..7202ee1da749 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1524,6 +1524,7 @@ #define PCI_DEVICE_ID_RICOH_RL5C476 0x0476 #define PCI_DEVICE_ID_RICOH_RL5C478 0x0478 #define PCI_DEVICE_ID_RICOH_R5C822 0x0822 +#define PCI_DEVICE_ID_RICOH_R5CE823 0xe823 #define PCI_DEVICE_ID_RICOH_R5C832 0x0832 #define PCI_DEVICE_ID_RICOH_R5C843 0x0843 -- cgit v1.2.3 From 6d872508383434ffb576d1d44e19c96c59cd064f Mon Sep 17 00:00:00 2001 From: Manoj Iyer Date: Mon, 11 Jul 2011 16:28:35 -0500 Subject: mmc: Added quirks for Ricoh 1180:e823 lower base clock [ upstream commit 15bed0f2fa8e1d7db201692532c210a7823d2d21 ] frequency Ricoh 1180:e823 does not recognize certain types of SD/MMC cards, as reported at http://launchpad.net/bugs/773524. Lowering the SD base clock frequency from 200Mhz to 50Mhz fixes this issue. This solution was suggest by Koji Matsumuro, Ricoh Company, Ltd. This change has no negative performance effect on standard SD cards, though it's quite possible that there will be one on UHS-1 cards. Signed-off-by: Manoj Iyer Tested-by: Daniel Manrique Cc: Koji Matsumuro Cc: Acked-by: Jesse Barnes Signed-off-by: Chris Ball Signed-off-by: Andi Kleen --- drivers/pci/quirks.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 19a81cf2b61f..12cb105c6cae 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2698,6 +2698,29 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n"); dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n"); + + /* + * RICOH 0xe823 SD/MMC card reader fails to recognize + * certain types of SD/MMC cards. Lowering the SD base + * clock frequency from 200Mhz to 50Mhz fixes this issue. + * + * 0x150 - SD2.0 mode enable for changing base clock + * frequency to 50Mhz + * 0xe1 - Base clock frequency + * 0x32 - 50Mhz new clock frequency + * 0xf9 - Key register for 0x150 + * 0xfc - key register for 0xe1 + */ + if (dev->device == PCI_DEVICE_ID_RICOH_R5CE823) { + pci_write_config_byte(dev, 0xf9, 0xfc); + pci_write_config_byte(dev, 0x150, 0x10); + pci_write_config_byte(dev, 0xf9, 0x00); + pci_write_config_byte(dev, 0xfc, 0x01); + pci_write_config_byte(dev, 0xe1, 0x32); + pci_write_config_byte(dev, 0xfc, 0x00); + + dev_notice(&dev->dev, "MMC controller base frequency changed to 50Mhz.\n"); + } } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); -- cgit v1.2.3 From 68a7b5709fe88c2ed64ff7e0d088ff4b85703169 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 1 Aug 2011 13:55:00 -0700 Subject: Drop -Werror in perf Drop -Werror in perf Makefile. This fixes the build with gcc 4.5.x Not in mainline. Signed-off-by: Andi Kleen --- tools/perf/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index d75c28a825f5..854652a83a83 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -225,7 +225,7 @@ ifndef PERF_DEBUG CFLAGS_OPTIMIZE = -O6 endif -CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) +CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) EXTLIBS = -lpthread -lrt -lelf -lm ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 ALL_LDFLAGS = $(LDFLAGS) -- cgit v1.2.3 From 16c6bf2102869f5d3afeaf26b0c14aeb1db7bcb7 Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Thu, 14 Jul 2011 09:34:37 +0800 Subject: kexec, x86: Fix incorrect jump back address if not [ upstream commit 050438ed5a05b25cdf287f5691e56a58c2606997 ] preserving context In kexec jump support, jump back address passed to the kexeced kernel via function calling ABI, that is, the function call return address is the jump back entry. Furthermore, jump back entry == 0 should be used to signal that the jump back or preserve context is not enabled in the original kernel. But in the current implementation the stack position used for function call return address is not cleared context preservation is disabled. The patch fixes this bug. Reported-and-tested-by: Yin Kangkai Signed-off-by: Huang Ying Cc: Eric W. Biederman Cc: Vivek Goyal Cc: Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/1310607277-25029-1-git-send-email-ying.huang@intel.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/relocate_kernel_32.S | 2 ++ arch/x86/kernel/relocate_kernel_64.S | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/x86/kernel/relocate_kernel_32.S b/arch/x86/kernel/relocate_kernel_32.S index 41235531b11c..36818f8ec2be 100644 --- a/arch/x86/kernel/relocate_kernel_32.S +++ b/arch/x86/kernel/relocate_kernel_32.S @@ -97,6 +97,8 @@ relocate_kernel: ret identity_mapped: + /* set return address to 0 if not preserving context */ + pushl $0 /* store the start address on the stack */ pushl %edx diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S index 4de8f5b3d476..7a6f3b3be3cf 100644 --- a/arch/x86/kernel/relocate_kernel_64.S +++ b/arch/x86/kernel/relocate_kernel_64.S @@ -100,6 +100,8 @@ relocate_kernel: ret identity_mapped: + /* set return address to 0 if not preserving context */ + pushq $0 /* store the start address on the stack */ pushq %rdx -- cgit v1.2.3 From 07979fe35895ea6e415cbb3c5551835b2df6bf51 Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Tue, 19 Jul 2011 11:25:38 +0200 Subject: USB: serial: add IDs for WinChipHead USB->RS232 adapter [ upstream commit 026dfaf18973404a01f488d6aa556a8c466e06a4 ] Add ID 4348:5523 for WinChipHead USB->RS 232 adapter with Prolifec PL2303 chipset Signed-off-by: Wolfgang Denk Cc: stable Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/serial/pl2303.c | 1 + drivers/usb/serial/pl2303.h | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 2fcc54ef04f9..0a7275eab03a 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -91,6 +91,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) }, { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) }, + { USB_DEVICE(WINCHIPHEAD_VENDOR_ID, WINCHIPHEAD_USBSER_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 1b025f75dafd..ca0d237683b3 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -144,3 +144,7 @@ /* ADLINK ND-6530 RS232,RS485 and RS422 adapter */ #define ADLINK_VENDOR_ID 0x0b63 #define ADLINK_ND6530_PRODUCT_ID 0x6530 + +/* WinChipHead USB->RS 232 adapter */ +#define WINCHIPHEAD_VENDOR_ID 0x4348 +#define WINCHIPHEAD_USBSER_PRODUCT_ID 0x5523 -- cgit v1.2.3 From 5671ba64a10a8150de56a8131cf0084381ca79ba Mon Sep 17 00:00:00 2001 From: Jon Povey Date: Tue, 19 Jul 2011 12:30:11 +0900 Subject: davinci: DM365 EVM: fix video input mux bits [ upstream commit 9daedd833a38edd90cf7baa1b1fcf61c3a0721e3 ] Video input mux settings for tvp7002 and imager inputs were swapped. Comment was correct. Tested on EVM with tvp7002 input. Signed-off-by: Jon Povey Acked-by: Manjunath Hadli Cc: stable@kernel.org Signed-off-by: Sekhar Nori Signed-off-by: Andi Kleen --- arch/arm/mach-davinci/board-dm365-evm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index 84acef1d0b3d..c3a4f29874be 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -520,7 +520,7 @@ fail: */ if (have_imager()) { label = "HD imager"; - mux |= 1; + mux |= 2; /* externally mux MMC1/ENET/AIC33 to imager */ mux |= BIT(6) | BIT(5) | BIT(3); @@ -541,7 +541,7 @@ fail: resets &= ~BIT(1); if (have_tvp7002()) { - mux |= 2; + mux |= 1; resets &= ~BIT(2); label = "tvp7002 HD"; } else { -- cgit v1.2.3 From bf7b6215667dd484edf6aa03b764927afc6a6c76 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 5 Jul 2011 21:51:36 +0000 Subject: powerpc/pseries/hvconsole: Fix dropped console output [ upstream commit 51d33021425e1f905beb4208823146f2fb6517da ] Return -EAGAIN when we get H_BUSY back from the hypervisor. This makes the hvc console driver retry, avoiding dropped printks. Signed-off-by: Anton Blanchard Cc: Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andi Kleen --- arch/powerpc/platforms/pseries/hvconsole.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/pseries/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c index 3f6a89b09816..041e87ca1893 100644 --- a/arch/powerpc/platforms/pseries/hvconsole.c +++ b/arch/powerpc/platforms/pseries/hvconsole.c @@ -73,7 +73,7 @@ int hvc_put_chars(uint32_t vtermno, const char *buf, int count) if (ret == H_SUCCESS) return count; if (ret == H_BUSY) - return 0; + return -EAGAIN; return -EIO; } -- cgit v1.2.3 From bf807eef020a66ee0597cd7996cf6d8bfb06945d Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Tue, 5 Jul 2011 21:50:18 +0000 Subject: hvc_console: Improve tty/console put_chars handling [ upstream commit 8c2381af0d3ef62a681dac5a141b6dabb27bf2e1 ] Currently, the hvc_console_print() function drops console output if the hvc backend's put_chars() returns 0. This patch changes this behavior to allow a retry through returning -EAGAIN. This change also affects the hvc_push() function. Both functions are changed to handle -EAGAIN and to retry the put_chars() operation. If a hvc backend returns -EAGAIN, the retry handling differs: - hvc_console_print() spins to write the complete console output. - hvc_push() behaves the same way as for returning 0. Now hvc backends can indirectly control the way how console output is handled through the hvc console layer. Signed-off-by: Hendrik Brueckner Acked-by: Anton Blanchard Cc: Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andi Kleen --- drivers/char/hvc_console.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 35cca4c7fb18..8417efec9ddb 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -163,8 +163,10 @@ static void hvc_console_print(struct console *co, const char *b, } else { r = cons_ops[index]->put_chars(vtermnos[index], c, i); if (r <= 0) { - /* throw away chars on error */ - i = 0; + /* throw away characters on error + * but spin in case of -EAGAIN */ + if (r != -EAGAIN) + i = 0; } else if (r > 0) { i -= r; if (i > 0) @@ -448,7 +450,7 @@ static int hvc_push(struct hvc_struct *hp) n = hp->ops->put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf); if (n <= 0) { - if (n == 0) { + if (n == 0 || n == -EAGAIN) { hp->do_wakeup = 1; return 0; } -- cgit v1.2.3 From 5d9a9233b7fe68dc51ee41a4d35798cfee682444 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Mon, 4 Jul 2011 20:40:10 +0000 Subject: powerpc/kdump: Fix timeout in crash_kexec_wait_realmode [ upstream commit 63f21a56f1cc0b800a4c00349c59448f82473d19 ] The existing code it pretty ugly. How about we clean it up even more like this? From: Anton Blanchard We check for timeout expiry in the outer loop, but we also need to check it in the inner loop or we can lock up forever waiting for a CPU to hit real mode. Signed-off-by: Anton Blanchard Signed-off-by: Michael Neuling Cc: Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andi Kleen --- arch/powerpc/kernel/crash.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 417f7b05a9ce..8fc58aae9332 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c @@ -176,12 +176,8 @@ static void crash_kexec_wait_realmode(int cpu) while (paca[i].kexec_state < KEXEC_STATE_REAL_MODE) { barrier(); - if (!cpu_possible(i)) { + if (!cpu_possible(i) || !cpu_online(i) || (msecs <= 0)) break; - } - if (!cpu_online(i)) { - break; - } msecs--; mdelay(1); } -- cgit v1.2.3 From f537ef79e7eca73f3d8161411d8da63fe346f7cc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 17 Jul 2011 00:24:37 -0300 Subject: si4713-i2c: avoid potential buffer overflow on si4713 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ upstream commit dc6b845044ccb7e9e6f3b7e71bd179b3cf0223b6 ] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While compiling it with Fedora 15, I noticed this issue: inlined from ‘si4713_write_econtrol_string’ at drivers/media/radio/si4713-i2c.c:1065:24: arch/x86/include/asm/uaccess_32.h:211:26: error: call to ‘copy_from_user_overflow’ declared with attribute error: copy_from_user() buffer size is not provably correct Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab Acked-by: Sakari Ailus Acked-by: Eduardo Valentin Reviewed-by: Eugene Teo Signed-off-by: Linus Torvalds Signed-off-by: Andi Kleen --- drivers/media/radio/si4713-i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/radio/si4713-i2c.c b/drivers/media/radio/si4713-i2c.c index ab63dd5b25c4..6ce2fb16f8fa 100644 --- a/drivers/media/radio/si4713-i2c.c +++ b/drivers/media/radio/si4713-i2c.c @@ -1004,7 +1004,7 @@ static int si4713_write_econtrol_string(struct si4713_device *sdev, char ps_name[MAX_RDS_PS_NAME + 1]; len = control->size - 1; - if (len > MAX_RDS_PS_NAME) { + if (len < 0 || len > MAX_RDS_PS_NAME) { rval = -ERANGE; goto exit; } @@ -1026,7 +1026,7 @@ static int si4713_write_econtrol_string(struct si4713_device *sdev, char radio_text[MAX_RDS_RADIO_TEXT + 1]; len = control->size - 1; - if (len > MAX_RDS_RADIO_TEXT) { + if (len < 0 || len > MAX_RDS_RADIO_TEXT) { rval = -ERANGE; goto exit; } -- cgit v1.2.3 From 57090d5ee1e6ecfd74ecdc376d1246ff53aabd03 Mon Sep 17 00:00:00 2001 From: Pavel Herrmann Date: Sun, 17 Jul 2011 18:39:19 +0200 Subject: hwmon: (max1111) Fix race condition causing NULL pointer [ upstream commit d3f684f2820a7f42acef68bea6622d9032127fb2 ] exception spi_sync call uses its spi_message parameter to keep completion information, using a drvdata structure is not thread-safe. Use a mutex to prevent multiple access to shared driver data. Signed-off-by: Pavel Herrmann Acked-by: Russell King Acked-by: Pavel Machek Acked-by: Marek Vasut Acked-by: Cyril Hrubis Tested-by: Stanislav Brabec Signed-off-by: Jean Delvare Cc: stable@kernel.org Signed-off-by: Andi Kleen --- drivers/hwmon/max1111.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c index 12a54aa29776..14335bbc9bdc 100644 --- a/drivers/hwmon/max1111.c +++ b/drivers/hwmon/max1111.c @@ -40,6 +40,8 @@ struct max1111_data { struct spi_transfer xfer[2]; uint8_t *tx_buf; uint8_t *rx_buf; + struct mutex drvdata_lock; + /* protect msg, xfer and buffers from multiple access */ }; static int max1111_read(struct device *dev, int channel) @@ -48,6 +50,9 @@ static int max1111_read(struct device *dev, int channel) uint8_t v1, v2; int err; + /* writing to drvdata struct is not thread safe, wait on mutex */ + mutex_lock(&data->drvdata_lock); + data->tx_buf[0] = (channel << MAX1111_CTRL_SEL_SH) | MAX1111_CTRL_PD0 | MAX1111_CTRL_PD1 | MAX1111_CTRL_SGL | MAX1111_CTRL_UNI | MAX1111_CTRL_STR; @@ -55,12 +60,15 @@ static int max1111_read(struct device *dev, int channel) err = spi_sync(data->spi, &data->msg); if (err < 0) { dev_err(dev, "spi_sync failed with %d\n", err); + mutex_unlock(&data->drvdata_lock); return err; } v1 = data->rx_buf[0]; v2 = data->rx_buf[1]; + mutex_unlock(&data->drvdata_lock); + if ((v1 & 0xc0) || (v2 & 0x3f)) return -EINVAL; @@ -176,6 +184,8 @@ static int __devinit max1111_probe(struct spi_device *spi) if (err) goto err_free_data; + mutex_init(&data->drvdata_lock); + data->spi = spi; spi_set_drvdata(spi, data); @@ -213,6 +223,7 @@ static int __devexit max1111_remove(struct spi_device *spi) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group); + mutex_destroy(&data->drvdata_lock); kfree(data->rx_buf); kfree(data->tx_buf); kfree(data); -- cgit v1.2.3 From 9c1f7a93bff756565bcb4e1b992541cb776f24d2 Mon Sep 17 00:00:00 2001 From: Luca Tettamanti Date: Sun, 17 Jul 2011 18:39:18 +0200 Subject: hwmon: (asus_atk0110) Fix memory leak [ upstream commit 0b8e77f12cb6bfe2e5a67f2cdc8c7af23abc4ccf ] The object returned by atk_gitm is dynamically allocated and must be freed. Signed-off-by: Luca Tettamanti Signed-off-by: Jean Delvare Cc: stable@kernel.org Signed-off-by: Andi Kleen --- drivers/hwmon/asus_atk0110.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index 653db1bda934..df17705b5938 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -655,6 +655,7 @@ static int atk_debugfs_gitm_get(void *p, u64 *val) else err = -EIO; + ACPI_FREE(ret); return err; } -- cgit v1.2.3 From 5464598561256330d2a14d9616921deb97b69103 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 15 Jul 2011 17:22:15 -0400 Subject: USB: OHCI: fix another regression for NVIDIA controllers [ upstream commit 6ea12a04d295235ed67010a09fdea58c949e3eb0 ] The NVIDIA series of OHCI controllers continues to be troublesome. A few people using the MCP67 chipset have reported that even with the most recent kernels, the OHCI controller fails to handle new connections and spams the system log with "unable to enumerate USB port" messages. This is different from the other problems previously reported for NVIDIA OHCI controllers, although it is probably related. It turns out that the MCP67 controller does not like to be kept in the RESET state very long. After only a few seconds, it decides not to work any more. This patch (as1479) changes the PCI initialization quirk code so that NVIDIA controllers are switched into the SUSPEND state after 50 ms of RESET. With no interrupts enabled and all the downstream devices reset, and thus unable to send wakeup requests, this should be perfectly safe (even for non-NVIDIA hardware). The removal code in ohci-hcd hasn't been changed; it will still leave the controller in the RESET state. As a result, if someone unloads ohci-hcd and then reloads it, the controller won't work again until the system is rebooted. If anybody complains about this, the removal code can be updated similarly. This fixes Bugzilla #22052. Tested-by: Larry Finger Cc: stable Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/pci-quirks.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 464ed977b45d..bcf7a88fe516 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -34,6 +34,8 @@ #define OHCI_INTRSTATUS 0x0c #define OHCI_INTRENABLE 0x10 #define OHCI_INTRDISABLE 0x14 +#define OHCI_FMINTERVAL 0x34 +#define OHCI_HCR (1 << 0) /* host controller reset */ #define OHCI_OCR (1 << 3) /* ownership change request */ #define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ #define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ @@ -204,6 +206,32 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) /* reset controller, preserving RWC (and possibly IR) */ writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL); + readl(base + OHCI_CONTROL); + + /* Some NVIDIA controllers stop working if kept in RESET for too long */ + if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) { + u32 fminterval; + int cnt; + + /* drive reset for at least 50 ms (7.1.7.5) */ + msleep(50); + + /* software reset of the controller, preserving HcFmInterval */ + fminterval = readl(base + OHCI_FMINTERVAL); + writel(OHCI_HCR, base + OHCI_CMDSTATUS); + + /* reset requires max 10 us delay */ + for (cnt = 30; cnt > 0; --cnt) { /* ... allow extra time */ + if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0) + break; + udelay(1); + } + writel(fminterval, base + OHCI_FMINTERVAL); + + /* Now we're in the SUSPEND state with all devices reset + * and wakeups and interrupts disabled + */ + } /* * disable interrupts -- cgit v1.2.3 From c20974dfa539046b0cec0af14a2d707c39f33b2a Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 9 Jul 2011 16:43:22 +0200 Subject: firewire: cdev: prevent race between first get_info ioctl [ upstream commit 93b37905f70083d6143f5f4dba0a45cc64379a62 ] and bus reset event queuing Between open(2) of a /dev/fw* and the first FW_CDEV_IOC_GET_INFO ioctl(2) on it, the kernel already queues FW_CDEV_EVENT_BUS_RESET events to be read(2) by the client. The get_info ioctl is practically always issued right away after open, hence this condition only occurs if the client opens during a bus reset, especially during a rapid series of bus resets. The problem with this condition is twofold: - These bus reset events carry the (as yet undocumented) @closure value of 0. But it is not the kernel's place to choose closures; they are privat to the client. E.g., this 0 value forced from the kernel makes it unsafe for clients to dereference it as a pointer to a closure object without NULL pointer check. - It is impossible for clients to determine the relative order of bus reset events from get_info ioctl(2) versus those from read(2), except in one way: By comparison of closure values. Again, such a procedure imposes complexity on clients and reduces freedom in use of the bus reset closure. So, change the ABI to suppress queuing of bus reset events before the first FW_CDEV_IOC_GET_INFO ioctl was issued by the client. Note, this ABI change cannot be version-controlled. The kernel cannot distinguish old from new clients before the first FW_CDEV_IOC_GET_INFO ioctl. We will try to back-merge this change into currently maintained stable/ longterm series, and we only document the new behaviour. The old behavior is now considered a kernel bug, which it basically is. Signed-off-by: Stefan Richter Cc: Signed-off-by: Andi Kleen --- drivers/firewire/core-cdev.c | 18 ++++++++++-------- include/linux/firewire-cdev.h | 3 +++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 5bf106b9d791..56728dd1381e 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -219,14 +219,11 @@ static int fw_device_op_open(struct inode *inode, struct file *file) idr_init(&client->resource_idr); INIT_LIST_HEAD(&client->event_list); init_waitqueue_head(&client->wait); + INIT_LIST_HEAD(&client->link); kref_init(&client->kref); file->private_data = client; - mutex_lock(&device->client_list_mutex); - list_add_tail(&client->link, &device->client_list); - mutex_unlock(&device->client_list_mutex); - return nonseekable_open(inode, file); } @@ -414,15 +411,20 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg) if (ret != 0) return -EFAULT; + mutex_lock(&client->device->client_list_mutex); + client->bus_reset_closure = a->bus_reset_closure; if (a->bus_reset != 0) { fill_bus_reset_event(&bus_reset, client); - if (copy_to_user(u64_to_uptr(a->bus_reset), - &bus_reset, sizeof(bus_reset))) - return -EFAULT; + ret = copy_to_user(u64_to_uptr(a->bus_reset), + &bus_reset, sizeof(bus_reset)); } + if (ret == 0 && list_empty(&client->link)) + list_add_tail(&client->link, &client->device->client_list); - return 0; + mutex_unlock(&client->device->client_list_mutex); + + return ret ? -EFAULT : 0; } static int add_client_resource(struct client *client, diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 68f883b30a53..2f2fe169222b 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -284,6 +284,9 @@ union fw_cdev_event { * of the bus. This does not cause a bus reset to happen. * @bus_reset_closure: Value of &closure in this and subsequent bus reset events * @card: The index of the card this device belongs to + * + * As a side effect, reception of %FW_CDEV_EVENT_BUS_RESET events to be read(2) + * is started by this ioctl. */ struct fw_cdev_get_info { __u32 version; -- cgit v1.2.3 From 5392dda6e2b429cdf8d72dcbe36481372e1caa14 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 9 Jul 2011 16:42:26 +0200 Subject: firewire: cdev: return -ENOTTY for unimplemented ioctls, not [ upstream commit d873d794235efa590ab3c94d5ee22bb1fab19ac4 ] -EINVAL On Jun 27 Linus Torvalds wrote: > The correct error code for "I don't understand this ioctl" is ENOTTY. > The naming may be odd, but you should think of that error value as a > "unrecognized ioctl number, you're feeding me random numbers that I > don't understand and I assume for historical reasons that you tried to > do some tty operation on me". [...] > The EINVAL thing goes way back, and is a disaster. It predates Linux > itself, as far as I can tell. You'll find lots of man-pages that have > this line in it: > > EINVAL Request or argp is not valid. > > and it shows up in POSIX etc. And sadly, it generally shows up > _before_ the line that says > > ENOTTY The specified request does not apply to the kind of object > that the descriptor d references. > > so a lot of people get to the EINVAL, and never even notice the ENOTTY. [...] > At least glibc (and hopefully other C libraries) use a _string_ that > makes much more sense: strerror(ENOTTY) is "Inappropriate ioctl for > device" So let's correct this in the ABI while it is still young, relative to distributor adoption. Side note: We return -ENOTTY not only on _IOC_TYPE or _IOC_NR mismatch, but also on _IOC_SIZE mismatch. An ioctl with an unsupported size of argument structure can be seen as an unsupported version of that ioctl. Signed-off-by: Stefan Richter Cc: Signed-off-by: Andi Kleen --- drivers/firewire/core-cdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 56728dd1381e..5816c46e701d 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1361,7 +1361,7 @@ static int dispatch_ioctl(struct client *client, if (_IOC_TYPE(cmd) != '#' || _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers) || _IOC_SIZE(cmd) > sizeof(buffer)) - return -EINVAL; + return -ENOTTY; if (_IOC_DIR(cmd) == _IOC_READ) memset(&buffer, 0, _IOC_SIZE(cmd)); -- cgit v1.2.3 From ccbe5280c9adf5955c0baeff57e8a549a27ebf46 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 29 Jun 2011 16:49:04 -0400 Subject: svcrpc: fix list-corrupting race on nfsd shutdown [ upstream commit ebc63e531cc6a457595dd110b07ac530eae788c3 ] After commit 3262c816a3d7fb1eaabce633caa317887ed549ae "[PATCH] knfsd: split svc_serv into pools", svc_delete_xprt (then svc_delete_socket) no longer removed its xpt_ready (then sk_ready) field from whatever list it was on, noting that there was no point since the whole list was about to be destroyed anyway. That was mostly true, but forgot that a few svc_xprt_enqueue()'s might still be hanging around playing with the about-to-be-destroyed list, and could get themselves into trouble writing to freed memory if we left this xprt on the list after freeing it. (This is actually functionally identical to a patch made first by Ben Greear, but with more comments.) Cc: stable@kernel.org Cc: gnb@fmeh.org Reported-by: Ben Greear Tested-by: Ben Greear Signed-off-by: J. Bruce Fields Signed-off-by: Andi Kleen --- net/sunrpc/svc_xprt.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 2f5fb71854d3..49aa3ff093a6 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -894,12 +894,13 @@ void svc_delete_xprt(struct svc_xprt *xprt) if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags)) list_del_init(&xprt->xpt_list); /* - * We used to delete the transport from whichever list - * it's sk_xprt.xpt_ready node was on, but we don't actually - * need to. This is because the only time we're called - * while still attached to a queue, the queue itself - * is about to be destroyed (in svc_destroy). + * The only time we're called while xpt_ready is still on a list + * is while the list itself is about to be destroyed (in + * svc_destroy). BUT svc_xprt_enqueue could still be attempting + * to add new entries to the sp_sockets list, so we can't leave + * a freed xprt on it. */ + list_del_init(&xprt->xpt_ready); if (test_bit(XPT_TEMP, &xprt->xpt_flags)) serv->sv_tmpcnt--; spin_unlock_bh(&serv->sv_lock); -- cgit v1.2.3 From ec43b20a4e00cccdf8705b60e3ddef95349fff6b Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Thu, 3 Jun 2010 23:22:28 -0400 Subject: x86: Look for IA32_ENERGY_PERF_BIAS support [ upstream commit 23016bf0 ] The new IA32_ENERGY_PERF_BIAS MSR allows system software to give hardware a hint whether OS policy favors more power saving, or more performance. This allows the OS to have some influence on internal hardware power/performance tradeoffs where the OS has previously had no influence. The support for this feature is indicated by CPUID.06H.ECX.bit3, as documented in the Intel Architectures Software Developer's Manual. This patch discovers support of this feature and displays it as "epb" in /proc/cpuinfo. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Andi Kleen LKML-Reference: Signed-off-by: Len Brown Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/cpufeature.h | 1 + arch/x86/include/asm/msr-index.h | 2 ++ arch/x86/kernel/cpu/addon_cpuid_features.c | 1 + 3 files changed, 4 insertions(+) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 14e0ee1b53f6..429e4f485746 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -162,6 +162,7 @@ #define X86_FEATURE_IDA (7*32+ 0) /* Intel Dynamic Acceleration */ #define X86_FEATURE_ARAT (7*32+ 1) /* Always Running APIC Timer */ #define X86_FEATURE_CPB (7*32+ 2) /* AMD Core Performance Boost */ +#define X86_FEATURE_EPB (7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */ /* Virtualization flags: Linux defined */ #define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */ diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 0639d9f2df67..7322e8744305 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -243,6 +243,8 @@ #define MSR_IA32_TEMPERATURE_TARGET 0x000001a2 +#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0 + /* MISC_ENABLE bits: architectural */ #define MSR_IA32_MISC_ENABLE_FAST_STRING (1ULL << 0) #define MSR_IA32_MISC_ENABLE_TCC (1ULL << 1) diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index 10fa5684a662..7369b4c2c55a 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c @@ -33,6 +33,7 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 }, { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 }, { X86_FEATURE_APERFMPERF, CR_ECX, 0, 0x00000006 }, + { X86_FEATURE_EPB, CR_ECX, 3, 0x00000006 }, { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007 }, { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a }, { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a }, -- cgit v1.2.3 From fb20c39467bbc0610039152704b8500f3539d666 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 14 Jul 2011 00:53:24 -0400 Subject: x86, intel, power: Initialize MSR_IA32_ENERGY_PERF_BIAS [ upstream commit abe48b108247e9b90b4c6739662a2e5c765ed114 ] Since 2.6.36 (23016bf0d25), Linux prints the existence of "epb" in /proc/cpuinfo, Since 2.6.38 (d5532ee7b40), the x86_energy_perf_policy(8) utility has been available in-tree to update MSR_IA32_ENERGY_PERF_BIAS. However, the typical BIOS fails to initialize the MSR, presumably because this is handled by high-volume shrink-wrap operating systems... Linux distros, on the other hand, do not yet invoke x86_energy_perf_policy(8). As a result, WSM-EP, SNB, and later hardware from Intel will run in its default hardware power-on state (performance), which assumes that users care for performance at all costs and not for energy efficiency. While that is fine for performance benchmarks, the hardware's intended default operating point is "normal" mode... Initialize the MSR to the "normal" by default during kernel boot. x86_energy_perf_policy(8) is available to change the default after boot, should the user have a different preference. Signed-off-by: Len Brown Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/alpine.LFD.2.02.1107140051020.18606@x980 Acked-by: Rafael J. Wysocki Signed-off-by: H. Peter Anvin Cc: --- arch/x86/include/asm/msr-index.h | 5 +++++ arch/x86/kernel/cpu/intel.c | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 7322e8744305..692c73bdc3fe 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -231,6 +231,11 @@ #define THERM_INT_LOW_ENABLE (1 << 0) #define THERM_INT_HIGH_ENABLE (1 << 1) +#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0 +#define ENERGY_PERF_BIAS_PERFORMANCE 0 +#define ENERGY_PERF_BIAS_NORMAL 6 +#define ENERGY_PERF_BIAS_POWERSWAVE 15 + #define MSR_IA32_THERM_STATUS 0x0000019c #define THERM_STATUS_PROCHOT (1 << 0) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index b4389441efbb..8e82a525b80c 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -450,6 +450,24 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) if (cpu_has(c, X86_FEATURE_VMX)) detect_vmx_virtcap(c); + + /* + * Initialize MSR_IA32_ENERGY_PERF_BIAS if BIOS did not. + * x86_energy_perf_policy(8) is available to change it at run-time + */ + if (cpu_has(c, X86_FEATURE_EPB)) { + u64 epb; + + rdmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb); + if ((epb & 0xF) == 0) { + printk_once(KERN_WARNING, "x86: updated energy_perf_bias" + " to 'normal' from 'performance'\n" + "You can view and update epb via utility," + " such as x86_energy_perf_policy(8)\n"); + epb = (epb & ~0xF) | ENERGY_PERF_BIAS_NORMAL; + wrmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb); + } + } } #ifdef CONFIG_X86_32 -- cgit v1.2.3 From 37f7a29f540ffaee81648ab757da701a7a8b3dcc Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Tue, 12 Jul 2011 10:27:55 -0700 Subject: SUNRPC: Fix use of static variable in rpcb_getport_async [ upstream commit ec0dd267bf7d08cb30e321e45a75fd40edd7e528 ] Because struct rpcbind_args *map was declared static, if two threads entered this method at the same time, the values assigned to map could be sent two two differen tasks. This could cause all sorts of problems, include use-after-free and double-free of memory. Fix this by removing the static declaration so that the map pointer is on the stack. Signed-off-by: Ben Greear Cc: stable@kernel.org Signed-off-by: Trond Myklebust Signed-off-by: Andi Kleen --- net/sunrpc/rpcb_clnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index dac219a56ae1..4db171f672ee 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -580,7 +580,7 @@ void rpcb_getport_async(struct rpc_task *task) u32 bind_version; struct rpc_xprt *xprt; struct rpc_clnt *rpcb_clnt; - static struct rpcbind_args *map; + struct rpcbind_args *map; struct rpc_task *child; struct sockaddr_storage addr; struct sockaddr *sap = (struct sockaddr *)&addr; -- cgit v1.2.3 From 16b9eeed2a368c85e42c680d7a25fee50c3ad828 Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Mon, 9 May 2011 14:41:46 +0300 Subject: ARM: pxa/cm-x300: fix V3020 RTC functionality [ upstream commit 6c7b3ea52e345ab614edb91d3f0e9f3bb3713871 ] While in sleep mode the CS# and other V3020 RTC GPIOs must be driven high, otherwise V3020 RTC fails to keep the right time in sleep mode. Signed-off-by: Igor Grinberg Cc: stable@kernel.org Signed-off-by: Eric Miao Signed-off-by: Andi Kleen --- arch/arm/mach-pxa/cm-x300.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index d717b49f0172..240455d6ec52 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -157,10 +157,10 @@ static mfp_cfg_t cm_x3xx_mfp_cfg[] __initdata = { GPIO99_GPIO, /* Ethernet IRQ */ /* RTC GPIOs */ - GPIO95_GPIO, /* RTC CS */ - GPIO96_GPIO, /* RTC WR */ - GPIO97_GPIO, /* RTC RD */ - GPIO98_GPIO, /* RTC IO */ + GPIO95_GPIO | MFP_LPM_DRIVE_HIGH, /* RTC CS */ + GPIO96_GPIO | MFP_LPM_DRIVE_HIGH, /* RTC WR */ + GPIO97_GPIO | MFP_LPM_DRIVE_HIGH, /* RTC RD */ + GPIO98_GPIO, /* RTC IO */ /* Standard I2C */ GPIO21_I2C_SCL, -- cgit v1.2.3 From 723df54958132696b5d203b6d8b9c914744983c2 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 10 Jul 2011 00:23:03 +0200 Subject: firewire: ohci: do not bind to Pinnacle cards, avert panic [ upstream commit 7f7e37115a8b6724f26d0637a04e1d35e3c59717 ] When firewire-ohci is bound to a Pinnacle MovieBoard, eventually a "Register access failure" is logged and an interrupt storm or a kernel panic happens. https://bugzilla.kernel.org/show_bug.cgi?id=36622 Until this is sorted out (if that is going to succeed at all), let's just prevent firewire-ohci from touching these devices. Signed-off-by: Stefan Richter Cc: Signed-off-by: Andi Kleen --- drivers/firewire/ohci.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 0942efb8d443..0ccc73c5ab2c 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -232,6 +232,7 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card) static char ohci_driver_name[] = KBUILD_MODNAME; #define PCI_DEVICE_ID_TI_TSB12LV22 0x8009 +#define PCI_VENDOR_ID_PINNACLE_SYSTEMS 0x11bd #define QUIRK_CYCLE_TIMER 1 #define QUIRK_RESET_PACKET 2 @@ -2480,6 +2481,11 @@ static int __devinit pci_probe(struct pci_dev *dev, int i, err, n_ir, n_it; size_t size; + if (dev->vendor == PCI_VENDOR_ID_PINNACLE_SYSTEMS) { + dev_err(&dev->dev, "Pinnacle MovieBoard is not yet supported\n"); + return -ENOSYS; + } + ohci = kzalloc(sizeof(*ohci), GFP_KERNEL); if (ohci == NULL) { err = -ENOMEM; -- cgit v1.2.3 From 8f8d6bc6ec9510a3bd8d97e011c7dc6008a7355d Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Fri, 8 Jul 2011 15:39:46 -0700 Subject: mm/nommu.c: fix remap_pfn_range() [ upstream commit 8f3b1327aa454bc8283e96bca7669c3c88b83f79 ] remap_pfn_range() means map physical address pfn<vm_start = pfn << PAGE_SHIFT which is wrong acroding the original meaning of this function. And some driver developer using remap_pfn_range() with correct parameter will get unexpected result because vm_start is changed. It should be implementd like addr = pfn << PAGE_SHIFT but which is meanless on nommu arch, this patch just make it simply return. Parameter name and setting of vma->vm_flags also be fixed. Signed-off-by: Bob Liu Cc: Geert Uytterhoeven Cc: David Howells Acked-by: Greg Ungerer Cc: Mike Frysinger Cc: Bob Liu Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Andi Kleen --- mm/nommu.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/mm/nommu.c b/mm/nommu.c index 3e1854887418..fbdb2e766758 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -1747,10 +1747,13 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address, return NULL; } -int remap_pfn_range(struct vm_area_struct *vma, unsigned long from, - unsigned long to, unsigned long size, pgprot_t prot) +int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, + unsigned long pfn, unsigned long size, pgprot_t prot) { - vma->vm_start = vma->vm_pgoff << PAGE_SHIFT; + if (addr != (pfn << PAGE_SHIFT)) + return -EINVAL; + + vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP; return 0; } EXPORT_SYMBOL(remap_pfn_range); -- cgit v1.2.3 From 81da73dccac71cbbd5949f87a7cacf2925f01e44 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 6 Jul 2011 23:19:38 +0400 Subject: EHCI: only power off port if over-current is active [ upstream commit 81463c1d707186adbbe534016cd1249edeab0dac ] MAX4967 USB power supply chip we use on our boards signals over-current when power is not enabled; once it's enabled, over-current signal returns to normal. That unfortunately caused the endless stream of "over-current change on port" messages. The EHCI root hub code reacts on every over-current signal change with powering off the port -- such change event is generated the moment the port power is enabled, so once enabled the power is immediately cut off. I think we should only cut off power when we're seeing the active over-current signal, so I'm adding such check to that code. I also think that the fact that we've cut off the port power should be reflected in the result of GetPortStatus request immediately, hence I'm adding a PORTSCn register readback after write... Signed-off-by: Sergei Shtylyov Cc: stable@kernel.org Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/usb/host/ehci-hub.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index e7d3d8def282..34053e795a83 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -837,10 +837,11 @@ static int ehci_hub_control ( * power switching; they're allowed to just limit the * current. khubd will turn the power back on. */ - if (HCS_PPC (ehci->hcs_params)){ + if ((temp & PORT_OC) && HCS_PPC(ehci->hcs_params)) { ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_POWER), status_reg); + temp = ehci_readl(ehci, status_reg); } } -- cgit v1.2.3 From 693560d364dc64efed3da660b62948368132754a Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 7 Jul 2011 23:33:39 +0530 Subject: mac80211: Restart STA timers only on associated state [ upstream commit 676b58c27475a9defccc025fea1cbd2b141ee539 ] A panic was observed when the device is failed to resume properly, and there are no running interfaces. ieee80211_reconfig tries to restart STA timers on unassociated state. Cc: stable@kernel.org Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville Signed-off-by: Andi Kleen --- net/mac80211/mlme.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 090b3e63ccf5..5ee5db66c2c7 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1995,6 +1995,9 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + if (!ifmgd->associated) + return; + if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running)) add_timer(&ifmgd->timer); if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) -- cgit v1.2.3 From 0e7d89101d9f1ab17f4123659bb796d7e4f7bcb8 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Fri, 8 Jul 2011 15:06:13 +0530 Subject: usb: musb: restore INDEX register in resume path [ upstream commit 3c5fec75e121b21a2eb35e5a6b44291509abba6f ] Restoring the missing INDEX register value in musb_restore_context(). Without this suspend resume functionality is broken with offmode enabled. Cc: stable@kernel.org Acked-by: Anand Gadiyar Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi Signed-off-by: Andi Kleen --- drivers/usb/musb/musb_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 006eaac791f4..809fed3f1c3e 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1697,6 +1697,7 @@ void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit) } } } + musb_writeb(musb_base, MUSB_INDEX, musb->context.index); } #else -- cgit v1.2.3 From 056f681640dc0ca20276dc15f7cbbc31b8641a1d Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 6 Jul 2011 19:58:23 -0400 Subject: SUNRPC: Fix a race between work-queue and rpc_killall_tasks [ upstream commit b55c59892e1f3b6c7d4b9ccffb4263e1486fb990 ] Since rpc_killall_tasks may modify the rpc_task's tk_action field without any locking, we need to be careful when dereferencing it. Reported-by: Ben Greear Tested-by: Ben Greear Signed-off-by: Trond Myklebust Cc: stable@kernel.org Signed-off-by: Andi Kleen --- net/sunrpc/sched.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index c55f753b09c0..f54059b5f320 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -623,30 +623,25 @@ static void __rpc_execute(struct rpc_task *task) BUG_ON(RPC_IS_QUEUED(task)); for (;;) { + void (*do_action)(struct rpc_task *); /* - * Execute any pending callback. + * Execute any pending callback first. */ - if (task->tk_callback) { - void (*save_callback)(struct rpc_task *); - - /* - * We set tk_callback to NULL before calling it, - * in case it sets the tk_callback field itself: - */ - save_callback = task->tk_callback; - task->tk_callback = NULL; - save_callback(task); - } else { + do_action = task->tk_callback; + task->tk_callback = NULL; + if (do_action == NULL) { /* * Perform the next FSM step. - * tk_action may be NULL when the task has been killed - * by someone else. + * tk_action may be NULL if the task has been killed. + * In particular, note that rpc_killall_tasks may + * do this at any time, so beware when dereferencing. */ - if (task->tk_action == NULL) + do_action = task->tk_action; + if (do_action == NULL) break; - task->tk_action(task); } + do_action(task); /* * Lockless check for whether task is sleeping or not. -- cgit v1.2.3 From 3db400fabd1f22b4bb4187142d0eb33efceff85a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 12 Jun 2011 07:02:43 -0300 Subject: bttv: fix s_tuner for radio [ upstream commit a024c1a6b274e11596d124619e43c25560f64c01 ] Fix typo: g_tuner should have been s_tuner. Tested with a bttv card. Cc: stable@kernel.org Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andi Kleen --- drivers/media/video/bt8xx/bttv-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 38c7f78ad9cf..9f8e8ad838ad 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -3525,7 +3525,7 @@ static int radio_s_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; - bttv_call_all(btv, tuner, g_tuner, t); + bttv_call_all(btv, tuner, s_tuner, t); return 0; } -- cgit v1.2.3 From f452581990ad01497dfefb023102d7dc49cbe75a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 12 Jun 2011 06:39:52 -0300 Subject: pvrusb2: fix g/s_tuner support [ upstream commit 50e9efd60b213ce43ad6979bfc18e25eec2d8413 ] The tuner-core subdev requires that the type field of v4l2_tuner is filled in correctly. This is done in v4l2-ioctl.c, but pvrusb2 doesn't use that yet, so we have to do it manually based on whether the current input is radio or not. Tested with my pvrusb2. Signed-off-by: Hans Verkuil Acked-by: Mike Isely Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andi Kleen --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 70ea578d6266..1c07a33fd6ba 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3039,6 +3039,8 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) if (hdw->input_dirty || hdw->audiomode_dirty || hdw->force_dirty) { struct v4l2_tuner vt; memset(&vt, 0, sizeof(vt)); + vt.type = (hdw->input_val == PVR2_CVAL_INPUT_RADIO) ? + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; vt.audmode = hdw->audiomode_val; v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, s_tuner, &vt); } @@ -5163,6 +5165,8 @@ void pvr2_hdw_status_poll(struct pvr2_hdw *hdw) { struct v4l2_tuner *vtp = &hdw->tuner_signal_info; memset(vtp, 0, sizeof(*vtp)); + vtp->type = (hdw->input_val == PVR2_CVAL_INPUT_RADIO) ? + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; hdw->tuner_signal_stale = 0; /* Note: There apparently is no replacement for VIDIOC_CROPCAP using v4l2-subdev - therefore we can't support that AT ALL right -- cgit v1.2.3 From 362a03ca4747dbbb67758e54df3d2fff6936e984 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 12 Jun 2011 06:36:41 -0300 Subject: v4l2-ioctl.c: prefill tuner type for g_frequency and [ upstream commit 227690df75382e46a4f6ea1bbc5df855a674b47f ] g/s_tuner The subdevs are supposed to receive a valid tuner type for the g_frequency and g/s_tuner subdev ops. Some drivers do this, others don't. So prefill this in v4l2-ioctl.c based on whether the device node from which this is called is a radio node or not. The spec does not require applications to fill in the type, and if they leave it at 0 then the 'check_mode' call in tuner-core.c will return an error and the ioctl does nothing. Cc: stable@kernel.org Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andi Kleen --- drivers/media/video/v4l2-ioctl.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 0eeceae50329..4ee6d53f6558 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -1644,6 +1644,8 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_g_tuner) break; + p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; ret = ops->vidioc_g_tuner(file, fh, p); if (!ret) dbgarg(cmd, "index=%d, name=%s, type=%d, " @@ -1662,6 +1664,8 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_s_tuner) break; + p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; dbgarg(cmd, "index=%d, name=%s, type=%d, " "capability=0x%x, rangelow=%d, " "rangehigh=%d, signal=%d, afc=%d, " @@ -1680,6 +1684,8 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_g_frequency) break; + p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; ret = ops->vidioc_g_frequency(file, fh, p); if (!ret) dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n", -- cgit v1.2.3 From 0b2e05879a5f73f75fb41d39b73ee35220d9a362 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 7 Jul 2011 18:24:54 +0200 Subject: mac80211: fix TKIP replay vulnerability [ upstream commit 34459512ffa7236c849466e3bd604801389734e1 ] Unlike CCMP, the presence or absence of the QoS field doesn't change the encryption, only the TID is used. When no QoS field is present, zero is used as the TID value. This means that it is possible for an attacker to take a QoS packet with TID 0 and replay it as a non-QoS packet. Unfortunately, mac80211 uses different IVs for checking the validity of the packet's TKIP IV when it checks TID 0 and when it checks non-QoS packets. This means it is vulnerable to this replay attack. To fix this, use the same replay counter for TID 0 and non-QoS packets by overriding the rx->queue value to 0 if it is 16 (non-QoS). This is a minimal fix for now. I caused this issue in commit 1411f9b531f0a910cd1c85a337737c1e6ffbae6a Author: Johannes Berg Date: Thu Jul 10 10:11:02 2008 +0200 mac80211: fix RX sequence number check while fixing a sequence number issue (there, a separate counter needs to be used). [AK: This was a non trivial backport. Johannes, John, please double check] Cc: stable@kernel.org Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Andi Kleen --- net/mac80211/wpa.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 0adbcc941ac9..78365d398042 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -89,6 +89,11 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; int authenticator = 1, wpa_test = 0; + int queue = rx->queue; + + /* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */ + if (rx->queue == NUM_RX_DATA_QUEUES - 1) + queue = 0; /* No way to verify the MIC if the hardware stripped it */ if (status->flag & RX_FLAG_MMIC_STRIPPED) @@ -130,8 +135,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) skb_trim(skb, skb->len - MICHAEL_MIC_LEN); /* update IV in key information to be able to detect replays */ - rx->key->u.tkip.rx[rx->queue].iv32 = rx->tkip_iv32; - rx->key->u.tkip.rx[rx->queue].iv16 = rx->tkip_iv16; + rx->key->u.tkip.rx[queue].iv32 = rx->tkip_iv32; + rx->key->u.tkip.rx[queue].iv16 = rx->tkip_iv16; return RX_CONTINUE; } @@ -213,6 +218,11 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) struct ieee80211_key *key = rx->key; struct sk_buff *skb = rx->skb; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + int queue = rx->queue; + + /* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */ + if (rx->queue == NUM_RX_DATA_QUEUES - 1) + queue = 0; hdrlen = ieee80211_hdrlen(hdr->frame_control); @@ -239,7 +249,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, key, skb->data + hdrlen, skb->len - hdrlen, rx->sta->sta.addr, - hdr->addr1, hwaccel, rx->queue, + hdr->addr1, hwaccel, queue, &rx->tkip_iv32, &rx->tkip_iv16); if (res != TKIP_DECRYPT_OK || wpa_test) -- cgit v1.2.3 From c7f88b2668a1fe87d6b0497081c03653c44ee80f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 6 Jul 2011 17:58:56 -0700 Subject: ASoC: ak4642: fixup snd_soc_update_bits mask for PW_MGMT2 [ upstream commit bd7fdbcaa2d06d446577fd3c9b81847b04469e01 ] mask didn't cover update-data Signed-off-by: Kuninori Morimoto Acked-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@kernel.org Signed-off-by: Andi Kleen --- sound/soc/codecs/ak4642.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 7528a54102b5..dc21971d9c83 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -319,7 +319,7 @@ static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) default: return -EINVAL; } - snd_soc_update_bits(codec, PW_MGMT2, MS, data); + snd_soc_update_bits(codec, PW_MGMT2, MS | MCKO | PMPLL, data); snd_soc_update_bits(codec, MD_CTL1, BCKO_MASK, bcko); return 0; -- cgit v1.2.3 From eabdd90b949f20ce315896b5bdd985a571d1bd77 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 5 Jul 2011 11:36:06 -0400 Subject: tracing: Fix bug when reading system filters on module [ upstream commit e9dbfae53eeb9fc3d4bb7da3df87fa9875f5da02 ] removal The event system is freed when its nr_events is set to zero. This happens when a module created an event system and then later the module is removed. Modules may share systems, so the system is allocated when it is created and freed when the modules are unloaded and all the events under the system are removed (nr_events set to zero). The problem arises when a task opened the "filter" file for the system. If the module is unloaded and it removed the last event for that system, the system structure is freed. If the task that opened the filter file accesses the "filter" file after the system has been freed, the system will access an invalid pointer. By adding a ref_count, and using it to keep track of what is using the event system, we can free it after all users are finished with the event system. Cc: Reported-by: Johannes Berg Signed-off-by: Steven Rostedt Signed-off-by: Andi Kleen --- kernel/trace/trace.h | 1 + kernel/trace/trace_events.c | 86 +++++++++++++++++++++++++++++++++----- kernel/trace/trace_events_filter.c | 6 +++ 3 files changed, 82 insertions(+), 11 deletions(-) diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 2cd96399463f..75ada72f55f8 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -731,6 +731,7 @@ struct event_subsystem { struct dentry *entry; struct event_filter *filter; int nr_events; + int ref_count; }; struct filter_pred; diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 53cffc0b0801..302a9f148c8f 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -182,6 +182,35 @@ static void ftrace_clear_events(void) mutex_unlock(&event_mutex); } +static void __put_system(struct event_subsystem *system) +{ + struct event_filter *filter = system->filter; + + WARN_ON_ONCE(system->ref_count == 0); + if (--system->ref_count) + return; + + if (filter) { + kfree(filter->filter_string); + kfree(filter); + } + kfree(system->name); + kfree(system); +} + +static void __get_system(struct event_subsystem *system) +{ + WARN_ON_ONCE(system->ref_count == 0); + system->ref_count++; +} + +static void put_system(struct event_subsystem *system) +{ + mutex_lock(&event_mutex); + __put_system(system); + mutex_unlock(&event_mutex); +} + /* * __ftrace_set_clr_event(NULL, NULL, NULL, set) will set/unset all events. */ @@ -704,6 +733,47 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, return cnt; } +static LIST_HEAD(event_subsystems); + +static int subsystem_open(struct inode *inode, struct file *filp) +{ + struct event_subsystem *system = NULL; + int ret; + + /* Make sure the system still exists */ + mutex_lock(&event_mutex); + list_for_each_entry(system, &event_subsystems, list) { + if (system == inode->i_private) { + /* Don't open systems with no events */ + if (!system->nr_events) { + system = NULL; + break; + } + __get_system(system); + break; + } + } + mutex_unlock(&event_mutex); + + if (system != inode->i_private) + return -ENODEV; + + ret = tracing_open_generic(inode, filp); + if (ret < 0) + put_system(system); + + return ret; +} + +static int subsystem_release(struct inode *inode, struct file *file) +{ + struct event_subsystem *system = inode->i_private; + + put_system(system); + + return 0; +} + static ssize_t subsystem_filter_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) @@ -836,9 +906,10 @@ static const struct file_operations ftrace_event_filter_fops = { }; static const struct file_operations ftrace_subsystem_filter_fops = { - .open = tracing_open_generic, + .open = subsystem_open, .read = subsystem_filter_read, .write = subsystem_filter_write, + .release = subsystem_release, }; static const struct file_operations ftrace_system_enable_fops = { @@ -872,8 +943,6 @@ static struct dentry *event_trace_events_dir(void) return d_events; } -static LIST_HEAD(event_subsystems); - static struct dentry * event_subsystem_dir(const char *name, struct dentry *d_events) { @@ -883,6 +952,7 @@ event_subsystem_dir(const char *name, struct dentry *d_events) /* First see if we did not already create this dir */ list_for_each_entry(system, &event_subsystems, list) { if (strcmp(system->name, name) == 0) { + __get_system(system); system->nr_events++; return system->entry; } @@ -905,6 +975,7 @@ event_subsystem_dir(const char *name, struct dentry *d_events) } system->nr_events = 1; + system->ref_count = 1; system->name = kstrdup(name, GFP_KERNEL); if (!system->name) { debugfs_remove(system->entry); @@ -1050,16 +1121,9 @@ static void remove_subsystem_dir(const char *name) list_for_each_entry(system, &event_subsystems, list) { if (strcmp(system->name, name) == 0) { if (!--system->nr_events) { - struct event_filter *filter = system->filter; - debugfs_remove_recursive(system->entry); list_del(&system->list); - if (filter) { - kfree(filter->filter_string); - kfree(filter); - } - kfree(system->name); - kfree(system); + __put_system(system); } break; } diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 57bb1bb32999..ecf4a3e1273a 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -1340,6 +1340,12 @@ int apply_subsystem_event_filter(struct event_subsystem *system, if (err) goto out_unlock; + /* Make sure the system still has events */ + if (!system->nr_events) { + err = -ENODEV; + goto out_unlock; + } + if (!strcmp(strstrip(filter_string), "0")) { filter_free_subsystem_preds(system); remove_filter_string(system->filter); -- cgit v1.2.3 From 788ae7963e9b103697d23a773dc1449533bf2e79 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 5 Jul 2011 14:32:51 -0400 Subject: tracing: Have "enable" file use refcounts like the "filter" [ upstream commit 40ee4dffff061399eb9358e0c8fcfbaf8de4c8fe ] file The "enable" file for the event system can be removed when a module is unloaded and the event system only has events from that module. As the event system nr_events count goes to zero, it may be freed if its ref_count is also set to zero. Like the "filter" file, the "enable" file may be opened by a task and referenced later, after a module has been unloaded and the events for that event system have been removed. Although the "filter" file referenced the event system structure, the "enable" file only references a pointer to the event system name. Since the name is freed when the event system is removed, it is possible that an access to the "enable" file may reference a freed pointer. Update the "enable" file to use the subsystem_open() routine that the "filter" file uses, to keep a reference to the event system structure while the "enable" file is opened. Cc: Reported-by: Johannes Berg Signed-off-by: Steven Rostedt Signed-off-by: Andi Kleen --- kernel/trace/trace_events.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 302a9f148c8f..83ff94a475ba 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -495,7 +495,7 @@ system_enable_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { const char set_to_char[4] = { '?', '0', '1', 'X' }; - const char *system = filp->private_data; + struct event_subsystem *system = filp->private_data; struct ftrace_event_call *call; char buf[2]; int set = 0; @@ -507,7 +507,7 @@ system_enable_read(struct file *filp, char __user *ubuf, size_t cnt, (!call->class->probe && !call->class->reg)) continue; - if (system && strcmp(call->class->system, system) != 0) + if (system && strcmp(call->class->system, system->name) != 0) continue; /* @@ -537,7 +537,8 @@ static ssize_t system_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { - const char *system = filp->private_data; + struct event_subsystem *system = filp->private_data; + const char *name = NULL; unsigned long val; char buf[64]; ssize_t ret; @@ -561,7 +562,14 @@ system_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, if (val != 0 && val != 1) return -EINVAL; - ret = __ftrace_set_clr_event(NULL, system, NULL, val); + /* + * Opening of "enable" adds a ref count to system, + * so the name is safe to use. + */ + if (system) + name = system->name; + + ret = __ftrace_set_clr_event(NULL, name, NULL, val); if (ret) goto out; @@ -740,6 +748,9 @@ static int subsystem_open(struct inode *inode, struct file *filp) struct event_subsystem *system = NULL; int ret; + if (!inode->i_private) + goto skip_search; + /* Make sure the system still exists */ mutex_lock(&event_mutex); list_for_each_entry(system, &event_subsystems, list) { @@ -758,8 +769,9 @@ static int subsystem_open(struct inode *inode, struct file *filp) if (system != inode->i_private) return -ENODEV; + skip_search: ret = tracing_open_generic(inode, filp); - if (ret < 0) + if (ret < 0 && system) put_system(system); return ret; @@ -769,7 +781,8 @@ static int subsystem_release(struct inode *inode, struct file *file) { struct event_subsystem *system = inode->i_private; - put_system(system); + if (system) + put_system(system); return 0; } @@ -913,9 +926,10 @@ static const struct file_operations ftrace_subsystem_filter_fops = { }; static const struct file_operations ftrace_system_enable_fops = { - .open = tracing_open_generic, + .open = subsystem_open, .read = system_enable_read, .write = system_enable_write, + .release = subsystem_release, }; static const struct file_operations ftrace_show_header_fops = { @@ -1003,8 +1017,7 @@ event_subsystem_dir(const char *name, struct dentry *d_events) "'%s/filter' entry\n", name); } - trace_create_file("enable", 0644, system->entry, - (void *)system->name, + trace_create_file("enable", 0644, system->entry, system, &ftrace_system_enable_fops); return system->entry; -- cgit v1.2.3 From dd4e598f13dd3e9c871034dd22ace5977fa4c37a Mon Sep 17 00:00:00 2001 From: Paul Parsons Date: Sun, 8 May 2011 01:54:33 +0000 Subject: ARM: pxa: fix PGSR register address calculation [ upstream commit beb0c9b056b1c23d2029b46a425362e9ccbeba01 ] The file mfp-pxa2xx.c defines a macro, PGSR(), which translates a gpio bank number to a PGSR register address. The function pxa2xx_mfp_suspend() erroneously passed in a gpio number instead of a gpio bank number. Signed-off-by: Paul Parsons Cc: stable@kernel.org Signed-off-by: Eric Miao Signed-off-by: Andi Kleen --- arch/arm/mach-pxa/mfp-pxa2xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c index 1d1419b73457..dfff1de92bf2 100644 --- a/arch/arm/mach-pxa/mfp-pxa2xx.c +++ b/arch/arm/mach-pxa/mfp-pxa2xx.c @@ -347,9 +347,9 @@ static int pxa2xx_mfp_suspend(struct sys_device *d, pm_message_t state) if ((gpio_desc[i].config & MFP_LPM_KEEP_OUTPUT) && (GPDR(i) & GPIO_bit(i))) { if (GPLR(i) & GPIO_bit(i)) - PGSR(i) |= GPIO_bit(i); + PGSR(gpio_to_bank(i)) |= GPIO_bit(i); else - PGSR(i) &= ~GPIO_bit(i); + PGSR(gpio_to_bank(i)) &= ~GPIO_bit(i); } } -- cgit v1.2.3 From 08b751d515c0f2745b3e3c6bc7ca5a3f2747fe28 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 6 Jul 2011 17:14:44 +0200 Subject: iommu/amd: Don't use MSI address range for DMA addresses [ upstream commit 17f5b569e09cfa3488eaa663cbf9feada2e789f5 ] Reserve the MSI address range in the address allocator so that MSI addresses are not handed out as dma handles. Cc: stable@kernel.org Signed-off-by: Joerg Roedel Signed-off-by: Andi Kleen --- arch/x86/kernel/amd_iommu.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 4424c73ba01e..e26ac4035754 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -1048,7 +1049,7 @@ static int alloc_new_range(struct dma_ops_domain *dma_dom, { int index = dma_dom->aperture_size >> APERTURE_RANGE_SHIFT; struct amd_iommu *iommu; - unsigned long i; + unsigned long i, old_size; #ifdef CONFIG_IOMMU_STRESS populate = false; @@ -1084,8 +1085,21 @@ static int alloc_new_range(struct dma_ops_domain *dma_dom, } } + old_size = dma_dom->aperture_size; dma_dom->aperture_size += APERTURE_RANGE_SIZE; + /* Reserve address range used for MSI messages */ + if (old_size < MSI_ADDR_BASE_LO && + dma_dom->aperture_size > MSI_ADDR_BASE_LO) { + unsigned long spage; + int pages; + + pages = iommu_num_pages(MSI_ADDR_BASE_LO, 0x10000, PAGE_SIZE); + spage = MSI_ADDR_BASE_LO >> PAGE_SHIFT; + + dma_ops_reserve_addresses(dma_dom, spage, pages); + } + /* Intialize the exclusion range if necessary */ for_each_iommu(iommu) { if (iommu->exclusion_start && -- cgit v1.2.3 From 1566cd03b690efb4d9997294cda9d0ac53ab3816 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 18 Jun 2011 22:34:34 -0500 Subject: staging: r8192e_pci: Handle duplicate PCI ID 0x10ec:0x8192 [ upstream commit 1c50bf7e415cf6ce9545dbecc2ac0d89d3916c53 ] conflict with rtl8192se There are two devices with PCI ID 0x10ec:0x8192, namely RTL8192E and RTL8192SE. The method of distinguishing them is by the revision ID at offset 0x8 of the PCI configuration space. If the value is 0x10, then the device uses rtl8192se for a driver. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/rtl8192e/r8192E_core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/staging/rtl8192e/r8192E_core.c b/drivers/staging/rtl8192e/r8192E_core.c index eb41402d1d37..ed028d677c7b 100644 --- a/drivers/staging/rtl8192e/r8192E_core.c +++ b/drivers/staging/rtl8192e/r8192E_core.c @@ -6334,6 +6334,7 @@ static int __devinit rtl8192_pci_probe(struct pci_dev *pdev, struct net_device *dev = NULL; struct r8192_priv *priv= NULL; u8 unit = 0; + u8 revisionid; #ifdef CONFIG_RTL8192_IO_MAP unsigned long pio_start, pio_len, pio_flags; @@ -6423,6 +6424,11 @@ static int __devinit rtl8192_pci_probe(struct pci_dev *pdev, pci_write_config_byte(pdev, 0x41, 0x00); + pci_read_config_byte(pdev, 0x08, &revisionid); + /* If the revisionid is 0x10, the device uses rtl8192se. */ + if (pdev->device == 0x8192 && revisionid == 0x10) + goto fail1; + pci_read_config_byte(pdev, 0x05, &unit); pci_write_config_byte(pdev, 0x05, unit & (~0x04)); -- cgit v1.2.3 From 8df2d5870c76436e31a68ee141636f6555f9c789 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Sun, 26 Jun 2011 12:56:22 +0400 Subject: staging: comedi: fix infoleak to userspace [ upstream commit 819cbb120eaec7e014e5abd029260db1ca8c5735 ] driver_name and board_name are pointers to strings, not buffers of size COMEDI_NAMELEN. Copying COMEDI_NAMELEN bytes of a string containing less than COMEDI_NAMELEN-1 bytes would leak some unrelated bytes. Signed-off-by: Vasiliy Kulikov Cc: stable Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/comedi/comedi_fops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index aeb2c00875cd..9b5df0ea0f7d 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -383,8 +383,8 @@ static int do_devinfo_ioctl(struct comedi_device *dev, /* fill devinfo structure */ devinfo.version_code = COMEDI_VERSION_CODE; devinfo.n_subdevs = dev->n_subdevices; - memcpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN); - memcpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN); + strlcpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN); + strlcpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN); if (read_subdev) devinfo.read_subdevice = read_subdev - dev->subdevices; -- cgit v1.2.3 From 225686544fb9af569ea70a46e11fe130c6da5bd2 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 16 Jun 2011 13:16:37 -0700 Subject: Staging: hv: netvsc: Fix a bug in accounting transmit slots [ upstream commit 9079ce691255792009c446d8c3382507b8d38635 ] The transmit slots were manipulated without proper locking. Fix this bug by making the variable tracking the transmit slots atomic. This patch should be ported to prior stable kernels 2.6.32 and later. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Hank Janssen Cc: stable Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/staging/hv/netvsc_drv.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index f1a7402f5d5b..0ad89cca375a 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -19,6 +19,7 @@ * Hank Janssen */ #include +#include #include #include #include @@ -45,7 +46,7 @@ struct net_device_context { /* point back to our device context */ struct vm_device *device_ctx; - unsigned long avail; + atomic_t avail; struct work_struct work; }; @@ -133,7 +134,9 @@ static void netvsc_xmit_completion(void *context) dev_kfree_skb_any(skb); - if ((net_device_ctx->avail += num_pages) >= PACKET_PAGES_HIWATER) + atomic_add(num_pages, &net_device_ctx->avail); + if (atomic_read(&net_device_ctx->avail) >= + PACKET_PAGES_HIWATER) netif_wake_queue(net); } @@ -159,7 +162,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) /* Add 1 for skb->data and additional one for RNDIS */ num_pages = skb_shinfo(skb)->nr_frags + 1 + 1; - if (num_pages > net_device_ctx->avail) + if (num_pages > atomic_read(&net_device_ctx->avail)) return NETDEV_TX_BUSY; /* Allocate a netvsc packet based on # of frags. */ @@ -218,7 +221,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) net->stats.tx_packets, net->stats.tx_bytes); - if ((net_device_ctx->avail -= num_pages) < PACKET_PAGES_LOWATER) + atomic_sub(num_pages, &net_device_ctx->avail); + if (atomic_read(&net_device_ctx->avail) < PACKET_PAGES_LOWATER) netif_stop_queue(net); } else { /* we are shutting down or bus overloaded, just drop packet */ @@ -406,7 +410,7 @@ static int netvsc_probe(struct device *device) net_device_ctx = netdev_priv(net); net_device_ctx->device_ctx = device_ctx; - net_device_ctx->avail = ring_size; + atomic_set(&net_device_ctx->avail, ring_size); dev_set_drvdata(device, net); INIT_WORK(&net_device_ctx->work, netvsc_send_garp); -- cgit v1.2.3 From 64779cb190a6ba7a03b658cd0584cef74fb9c208 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 1 Jul 2011 14:38:12 +0100 Subject: ARM: 6989/1: perf: do not start the PMU when no events are [ upstream commit f4f38430c94c38187db73a2cf3892cc8b12a2713 ] present armpmu_enable can be called in situations where no events are present (for example, from the event rotation tick after a profiled task has exited). In this case, we currently start the PMU anyway which may leave it active inevitably without any events being monitored. This patch adds a simple check to the enabling code so that we avoid starting the PMU when no events are present. Cc: Reported-by: Ashwin Chaugle Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Andi Kleen --- arch/arm/kernel/perf_event.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index de12536d687f..2297594224da 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -531,7 +531,7 @@ void hw_perf_enable(void) { /* Enable all of the perf events on hardware. */ - int idx; + int idx, enabled = 0; struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); if (!armpmu) @@ -544,9 +544,11 @@ hw_perf_enable(void) continue; armpmu->enable(&event->hw, idx); + enabled = 1; } - armpmu->start(); + if (enabled) + armpmu->start(); } void -- cgit v1.2.3 From 507e949027b3dc00f56a1c91b88c2d899e9eaea0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 1 Jul 2011 17:24:46 -0700 Subject: ASoC: Ensure we delay long enough for WM8994 FLL to lock [ upstream commit 8e9ddf811ba021506d2316fcfe619faa0ab3f567 ] when starting This delay is very conservative. Signed-off-by: Mark Brown Acked-by: Liam Girdwood Cc: stable@kernel.org Signed-off-by: Andi Kleen --- sound/soc/codecs/wm8994.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index e84a1177f350..b458dc736921 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2929,6 +2929,8 @@ static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset, WM8994_FLL1_ENA | WM8994_FLL1_FRAC, reg); + + msleep(5); } wm8994->fll[id].in = freq_in; -- cgit v1.2.3 From 552fe3d630bed45d7b75c76d12b61e458b587de0 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 27 Jun 2011 14:26:56 +0100 Subject: SERIAL: SC26xx: Fix link error. [ upstream commit f2eb3cdf14457fccb14ae8c4d7d7cee088cd3957 ] Kconfig allows enabling console support for the SC26xx driver even when it's configured as a module resulting in a: ERROR: "uart_console_device" [drivers/tty/serial/sc26xx.ko] undefined! modpost error since the driver was merged in eea63e0e8a60d00485b47fb6e75d9aa2566b989b [SC26XX: New serial driver for SC2681 uarts] in 2.6.25. Fixed by only allowing console support to be enabled if the driver is builtin. Signed-off-by: Ralf Baechle Cc: linux-serial@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Cc: stable Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andi Kleen --- drivers/serial/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 8b23165bc5dc..1356eab002b6 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -1417,7 +1417,7 @@ config SERIAL_SC26XX config SERIAL_SC26XX_CONSOLE bool "Console on SC2681/SC2692 serial port" - depends on SERIAL_SC26XX + depends on SERIAL_SC26XX=y select SERIAL_CORE_CONSOLE help Support for Console on SC2681/SC2692 serial ports. -- cgit v1.2.3 From 22950d253543188b3e6488a0dbd5cad9eb71bef7 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 23 Jun 2011 11:19:26 -0700 Subject: x86, mtrr: lock stop machine during MTRR rendezvous sequence [ upstream commit 6d3321e8e2b3bf6a5892e2ef673c7bf536e3f904 ] MTRR rendezvous sequence using stop_one_cpu_nowait() can potentially happen in parallel with another system wide rendezvous using stop_machine(). This can lead to deadlock (The order in which works are queued can be different on different cpu's. Some cpu's will be running the first rendezvous handler and others will be running the second rendezvous handler. Each set waiting for the other set to join for the system wide rendezvous, leading to a deadlock). MTRR rendezvous sequence is not implemented using stop_machine() as this gets called both from the process context aswell as the cpu online paths (where the cpu has not come online and the interrupts are disabled etc). stop_machine() works with only online cpus. For now, take the stop_machine mutex in the MTRR rendezvous sequence that gets called from an online cpu (here we are in the process context and can potentially sleep while taking the mutex). And the MTRR rendezvous that gets triggered during cpu online doesn't need to take this stop_machine lock (as the stop_machine() already ensures that there is no cpu hotplug going on in parallel by doing get_online_cpus()) TBD: Pursue a cleaner solution of extending the stop_machine() infrastructure to handle the case where the calling cpu is still not online and use this for MTRR rendezvous sequence. fixes: https://bugzilla.novell.com/show_bug.cgi?id=672008 Reported-by: Vadim Kotelnikov Signed-off-by: Suresh Siddha Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/20110623182056.807230326@sbsiddha-MOBL3.sc.intel.com Cc: stable@kernel.org # 2.6.35+, backport a week or two after this gets more testing in mainline Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/mtrr/main.c | 23 +++++++++++++++++++++++ include/linux/stop_machine.h | 2 ++ kernel/stop_machine.c | 2 +- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 151787e382c7..172891ca9d65 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -247,6 +247,25 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ unsigned long flags; int cpu; +#ifdef CONFIG_SMP + /* + * If this cpu is not yet active, we are in the cpu online path. There + * can be no stop_machine() in parallel, as stop machine ensures this + * by using get_online_cpus(). We can skip taking the stop_cpus_mutex, + * as we don't need it and also we can't afford to block while waiting + * for the mutex. + * + * If this cpu is active, we need to prevent stop_machine() happening + * in parallel by taking the stop cpus mutex. + * + * Also, this is called in the context of cpu online path or in the + * context where cpu hotplug is prevented. So checking the active status + * of the raw_smp_processor_id() is safe. + */ + if (cpu_active(raw_smp_processor_id())) + mutex_lock(&stop_cpus_mutex); +#endif + preempt_disable(); data.smp_reg = reg; @@ -329,6 +348,10 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ local_irq_restore(flags); preempt_enable(); +#ifdef CONFIG_SMP + if (cpu_active(raw_smp_processor_id())) + mutex_unlock(&stop_cpus_mutex); +#endif } /** diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h index 6b524a0d02e4..df2c04e92305 100644 --- a/include/linux/stop_machine.h +++ b/include/linux/stop_machine.h @@ -27,6 +27,8 @@ struct cpu_stop_work { struct cpu_stop_done *done; }; +extern struct mutex stop_cpus_mutex; + int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg); void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg, struct cpu_stop_work *work_buf); diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 70f8d90331e9..44b3163defe3 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -132,8 +132,8 @@ void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg, cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu), work_buf); } +DEFINE_MUTEX(stop_cpus_mutex); /* static data for stop_cpus */ -static DEFINE_MUTEX(stop_cpus_mutex); static DEFINE_PER_CPU(struct cpu_stop_work, stop_cpus_work); int __stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg) -- cgit v1.2.3 From ea626c8fccc5b119bf1d398d99e7ecad4bfc95e2 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 3 Sep 2010 03:04:20 +0000 Subject: ipv6: add special mode forwarding=2 to send RS while [ upstream commit c3bccac2fa76f1619dfe4fb7b9bee69de7f066d8 ] configured as router Similar to accepting router advertisement, the IPv6 stack does not send router solicitations if forwarding is enabled. This patch enables this behavior to be overruled by setting forwarding to the special value 2. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller Signed-off-by: Andi Kleen --- net/ipv6/addrconf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index b5ab939d4d92..5d59520ae162 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2960,7 +2960,8 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) start sending router solicitations. */ - if (ifp->idev->cnf.forwarding == 0 && + if ((ifp->idev->cnf.forwarding == 0 || + ifp->idev->cnf.forwarding == 2) && ifp->idev->cnf.rtr_solicits > 0 && (dev->flags&IFF_LOOPBACK) == 0 && (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) { -- cgit v1.2.3 From 8904f07a1b5683c4363b225cb376f2bd1435246f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Luis=20V=C3=A1zquez=20Cao?= Date: Mon, 13 Jun 2011 15:04:43 +0000 Subject: IGMP snooping: set mrouters_only flag for IPv4 traffic [ upstream commit 62b2bcb49cca72f6d3f39f831127a6ab315a475d ] properly Upon reception of a IGMP/IGMPv2 membership report the kernel sets the mrouters_only flag in a skb that may be a clone of the original skb, which means that sometimes the bridge loses track of membership report packets (cb buffers are tied to a specific skb and not shared) and it ends up forwading join requests to the bridge interface. This can cause unexpected membership timeouts and intermitent/permanent loss of connectivity as described in RFC 4541 [2.1.1. IGMP Forwarding Rules]: A snooping switch should forward IGMP Membership Reports only to those ports where multicast routers are attached. [...] Sending membership reports to other hosts can result, for IGMPv1 and IGMPv2, in unintentionally preventing a host from joining a specific multicast group. Signed-off-by: Fernando Luis Vazquez Cao Tested-by: Hayato Kakuta Signed-off-by: David S. Miller Signed-off-by: Andi Kleen --- net/bridge/br_multicast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 5a9bcfe981c8..7ab8ad30adcd 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1403,7 +1403,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, switch (ih->type) { case IGMP_HOST_MEMBERSHIP_REPORT: case IGMPV2_HOST_MEMBERSHIP_REPORT: - BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; + BR_INPUT_SKB_CB(skb)->mrouters_only = 1; err = br_ip4_multicast_add_group(br, port, ih->group); break; case IGMPV3_HOST_MEMBERSHIP_REPORT: -- cgit v1.2.3 From ef0c3e7d6e082b7f3cf41546525c84f4477a76d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Luis=20V=C3=A1zquez=20Cao?= Date: Mon, 13 Jun 2011 15:06:58 +0000 Subject: IGMP snooping: set mrouters_only flag for IPv6 traffic [ upstream commit fc2af6c73fc9449cd5894a36bb76b8f8c0e49fd8 ] properly Upon reception of a MGM report packet the kernel sets the mrouters_only flag in a skb that is a clone of the original skb, which means that the bridge loses track of MGM packets (cb buffers are tied to a specific skb and not shared) and it ends up forwading join requests to the bridge interface. This can cause unexpected membership timeouts and intermitent/permanent loss of connectivity as described in RFC 4541 [2.1.1. IGMP Forwarding Rules]: A snooping switch should forward IGMP Membership Reports only to those ports where multicast routers are attached. [...] Sending membership reports to other hosts can result, for IGMPv1 and IGMPv2, in unintentionally preventing a host from joining a specific multicast group. Signed-off-by: Fernando Luis Vazquez Cao Signed-off-by: David S. Miller Signed-off-by: Andi Kleen --- net/bridge/br_multicast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 7ab8ad30adcd..382a4288c518 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1517,7 +1517,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, case ICMPV6_MGM_REPORT: { struct mld_msg *mld = (struct mld_msg *)icmp6h; - BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; + BR_INPUT_SKB_CB(skb)->mrouters_only = 1; err = br_ip6_multicast_add_group(br, port, &mld->mld_mca); break; } -- cgit v1.2.3 From 675f7660ffb0e1880011f6b3c4f9ac241491e3cd Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 1 Aug 2011 13:56:51 -0700 Subject: release 2.6.35.14 Signed-off-by: Andi Kleen --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a3d866b2e81e..45759718a179 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 35 -EXTRAVERSION = .13 +EXTRAVERSION = .14 NAME = Yokohama # *DOCUMENTATION* -- cgit v1.2.3